jQueryでヘッダー固定時のアンカーリンク対策 ― レスポンシブ対応

はじめに

固定ヘッダー(position: fixed)を使ったサイトでアンカーリンクをそのまま使うと、リンク先のコンテンツがヘッダーの裏に隠れてしまう問題が発生します。本記事では jQueryと matchMedia を組み合わせて、PCとスマートフォンで異なるヘッダー高さに対応したスムーズスクロールを実装する方法を解説します。

基本の実装コード

javascript

$(function () {
  // ブレイクポイントでヘッダー高さを切り替え
  var headerHeight = window.matchMedia('(min-width: 769px)').matches ? 160 : 80;

  $('a[href^=#]').click(function () {
    var href = $(this).attr('href');
    var target = $(href === '#' || href === '' ? 'html' : href);
    var position = target.offset().top - headerHeight;

    $('html, body').animate({ scrollTop: position }, 550, 'swing');
    return false;
  });
});
JavaScript

コードの解説

① matchMedia でレスポンシブ対応

javascript

var headerHeight = window.matchMedia('(min-width: 769px)').matches ? 160 : 80;
JavaScript

window.matchMedia() はCSSのメディアクエリをJavaScriptで判定できるAPIです。画面幅が 769px以上ならPC用の高さ(160px)、それ未満ならスマホ用の高さ(80px) をオフセット値として使います。

ポイント: ヘッダー高さはCSSの実際の値に合わせて調整してください。

② アンカーリンクのクリックイベント

javascript

$('a[href^=#]').click(function () { ... });
JavaScript

href 属性が # から始まるリンクすべてに対してクリックイベントを設定します。

③ スクロール先の位置を計算

javascript

var position = target.offset().top - headerHeight;
JavaScript

offset().top で対象要素のページ上部からの距離を取得し、ヘッダー高さ分を引くことで、コンテンツが隠れない正確な位置に移動できます。

④ スムーズスクロール

javascript

$('html, body').animate({ scrollTop: position }, 550, 'swing');
JavaScript
  • 550:スクロール速度(ミリ秒)
  • "swing":イージング("linear" に変えると等速スクロールになります)

応用:画面リサイズにも対応する

ページ読み込み時だけでなく、ウィンドウのリサイズ時にも高さを再取得したい場合は以下のように書き換えます。

javascript

$(function () {
  function getHeaderHeight() {
    return window.matchMedia('(min-width: 769px)').matches ? 160 : 80;
  }

  $('a[href^=#]').click(function () {
    var href = $(this).attr('href');
    var target = $(href === '#' || href === '' ? 'html' : href);
    var position = target.offset().top - getHeaderHeight(); // 毎回取得

    $('html, body').animate({ scrollTop: position }, 550, 'swing');
    return false;
  });
});
JavaScript

応用:URLハッシュ付きで直接アクセスした場合にも対応

別ページから page.html#section のようにアクセスした場合、読み込み直後にブラウザが自動スクロールしてヘッダーに隠れてしまうことがあります。以下のコードで対処できます。

javascript

$(window).on('load', function () {
  if (location.hash) {
    var headerHeight = window.matchMedia('(min-width: 769px)').matches ? 160 : 80;
    var target = $(location.hash);
    if (target.length) {
      var position = target.offset().top - headerHeight;
      $('html, body').scrollTop(position);
    }
  }
});
JavaScript

補足:CSSだけで解決する方法(モダンブラウザ向け)

jQueryを使わない場合、CSSの scroll-margin-top プロパティが便利です。

css

/* アンカーターゲットになる要素に設定 */
section, h2, h3 {
  scroll-margin-top: 160px; /* ヘッダーの高さ */
}

@media (max-width: 768px) {
  section, h2, h3 {
    scroll-margin-top: 80px;
  }
}
CSS

あわせて htmlscroll-behavior: smooth; を指定すればjQueryなしでスムーズスクロールも実現できます。ただし IE非対応 のため、レガシーブラウザのサポートが必要な場合はjQuery版を使用してください。

まとめ

方法対応ブラウザ柔軟性
jQuery + matchMediaIE含む広範囲高い(細かく制御可能)
CSS scroll-margin-topモダンブラウザのみシンプルで手軽

固定ヘッダーのアンカーリンク問題はサイト制作でよく遭遇する課題です。プロジェクトの要件に合わせて適切な方法を選んでください。

read next