質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.23%

同ページ内リンクで遷移したとき、jQueryで固定ヘッダー分の高さ合わせをしたい(レスポンシブ対応)

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,601

gtgt

score 5

現在の状況

jQueryにて、a href=“xxx.html#sample” のようなid指定付きリンクを使用したときに、固定されたヘッダーの高さ分を調整して飛ぶようなコードを組んでいます。
レスポンシブ対応で、ウインドウの横幅に応じて固定ヘッダーの高さが変わるので、ヘッダーの高さは条件分岐で設定しています。
使用コードは以下です。

// 別ページからのリンクで高さ合わせ
$(window).on('load', function() {
  var windowWidth = $(window).width();
  var windowSm = 767; // スマホに切り替わる横幅
    if (windowSm >= windowWidth) {
     var headerHeight = 80; // スマホのheaderの高さ
   }  else {
     var headerHeight = 140; // pcのheaderの高さ
    }
  if(document.URL.match("#")) {
  var str = location.href ;
  var cut_str = "#";
  var index = str.indexOf(cut_str);
  var href = str.slice(index);
  var target = href;
  var position = $(target).offset().top - headerHeight;
  $("html, body").scrollTop(position);
  return false;
}
});

// ページ内リンクで高さ合わせ
jQuery(function(){
  var windowWidth = $(window).width();
  var windowSm = 767; // スマホに切り替わる横幅
    if (windowSm >= windowWidth) {
     var headerHeight = 80; // スマホのheaderの高さ
   }  else {
     var headerHeight = 140; // pcのheaderの高さ
    }
    jQuery('a[href^="#"]').click(function() {
    var speed = 500;
    var href= jQuery(this).attr("href");
    var target = jQuery(href == "#" || href == "" ? 'html' : href);
    var position = target.offset().top-headerHeight;
    jQuery('body,html').animate({scrollTop:position}, speed, 'swing');
    return false;
   });
});

参照:
https://bn-ic.sakura.ne.jp/memo/menu_fixed
https://webcreator.me/blog/427/

起きている問題

別ページに飛んだときは正しく動作し、ヘッダー分の高さだけ位置をずらして飛ぶことができています。レスポンシブにも対応できました。
しかし、同ページ内で遷移したときに高さの調節が効いていないようで、idを指定しているdivセクションのh2見出しがheaderに隠れてしまいます。

補足情報

jQueryバージョンは3.4.1です。

お力を貸していただけたら幸いです。よろしくお願いします。

2019.10.15追記

ご指摘がありましたので、当該html/cssも載せます。
SSIによってメニューバーを含むヘッダーを共通化しています。サーバーはロリポップ!です。

index.htmlが以下。

<!--#include virtual="./header.html" -->

<div class="container" id="1">
  <div class="row">
    <h2>見出し1</h2>
    ここにコンテンツ1
  </div>
</div>

<div class="wrapper" id="2">
  <div class="container">
    <div class="row">
    <h2>見出し2</h2>
      ここにコンテンツ
    </div>
  </div>
</div>

SSIで呼び出しているheader.htmlが以下。

<header>
  <nav>
    <div class="container">
      <div class="row">
         <div class="col-md-4">
           <h1><a href="index.html">サイトタイトル</a></h1>
         </div>
         <div class="col-md-8">
            <ul class="d-none d-md-flex">
             <li><a href="works.html">リスト1</a></li>
             <li><a href="index.html#1">リスト2</a></li>
             <li><a href="index.html#2">リスト3</a></li>
             <li><a href="mailform.html">メールフォーム</a></li>
           </ul>
         </div>
      </div>
  </nav>
</header>


header.htmlは、index.html以外のページにおいても、SSIを用いて共通パーツとして呼び出しています。

ヘッダーを固定するのは、ある程度スクロールしたらnavに.is-fixedクラスを付与する形で行っています。jsおよびCSSは以下。

    $(function() {
var $win = $(window),
    $main = $('main'),
    $nav = $('nav'),
    navHeight = $nav.outerHeight(),
    navPos = $nav.offset().top,
    fixedClass = 'is-fixed';

$win.on('load scroll', function() {
  var value = $(this).scrollTop();
  if ( value > navPos ) {
    $nav.addClass(fixedClass);
    $main.css('margin-top', navHeight);
  } else {
    $nav.removeClass(fixedClass);
    $main.css('margin-top', '0');
  }
});
});
.is-fixed {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1000;
  box-shadow: 0px 0px 6px 3px rgba(79, 79, 79, 0.26);
}

なお、CSSでのheader・navのheight値の指定はしていません。

高さ合わせが上手くいく例
◯works.htmlにいる状態で、index.html#2へのリンクをクリックする(別ページ遷移)

高さ合わせが上手くいかない例
×index.htmlにいる状態で、index.html#2へのリンクをクリックする(同ページ内遷移)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • x_x

    2019/10/15 11:46

    問題が再現する HTML・CSS も書いてください。

    キャンセル

  • gtgt

    2019/10/15 12:53

    質問に追記する形で書きました。
    ご確認よろしくお願いします。

    キャンセル

  • x_x

    2019/10/15 13:01

    h2 がないようですが

    キャンセル

  • gtgt

    2019/10/15 14:04

    コードおよび質問文を修正しました。
    最初の質問文に「idを指定しているh2見出しが隠れる」とありましたが、「idを指定しているdivセクションのh2見出しが隠れる」の誤りでした。
    現状、idを指定しているのはh2ではなくdivです。(当初はh2にid指定していましたが、見出しが隠れることを受けてdivに指定し直しました。その名残でh2にidを指定している、との書き方をしてしまいました。大変失礼いたしました)

    キャンセル

回答 1

checkベストアンサー

+1

'a[href^="#"]' というのは属性値が "#" で始まることを前提とした簡易処理なので、前提がない場合はちゃんと判定する必要があります。

  var documentUrl = location.origin + location.pathname + location.search;
  jQuery(document).on('click', 'a[href*="#"]', function(event) {
    var anchor = event.currentTarget;
    var anchorUrl = anchor.protocol + '//' + anchor.host + anchor.pathname + anchor.search;
    if (documentUrl !== anchorUrl) {
      return true;
    }

    var speed = 500;
    var position = $(anchor.hash).offset().top - headerHeight;
    jQuery('body,html').animate({ scrollTop: position }, speed, 'swing');
    event.preventDefault();
    return false;
  });


https://developer.mozilla.org/ja/docs/Web/API/Location
https://developer.mozilla.org/ja/docs/Web/API/HTMLHyperlinkElementUtils

関連:
https://teratail.com/questions/118836
https://teratail.com/questions/198796

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/10/19 17:49

    ご回答いただいたコードにて、意図したとおりの挙動をするようになりました。
    参考URLも活用させていただきます。
    丁寧な対応、ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.23%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • jQueryに関する質問
  • 同ページ内リンクで遷移したとき、jQueryで固定ヘッダー分の高さ合わせをしたい(レスポンシブ対応)