position: fixed や position: sticky の固定ヘッダーがあると、ページ内リンクでジャンプした際にコンテンツがヘッダーの下に隠れてしまいます。この記事ではヘッダー高さの取得・scroll-margin-topによるCSS解決・jQueryでのアンカースクロール補正・レスポンシブ対応まで解説します。
この記事でわかること
- 固定ヘッダーの高さをjQueryで取得する
- scroll-margin-top(CSSのみ)で固定ヘッダーを考慮したスクロールにする
- jQueryでページ内リンクのスクロールをヘッダー高さ分補正する
- ウィンドウリサイズ時にヘッダー高さを再取得する
- CSS変数で動的にヘッダー高さを管理する
ヘッダーの高さをjQueryで取得する
$(function () {
// outerHeight() でpaddingとborderを含む高さを取得
var headerH = $('#site-header').outerHeight();
console.log('ヘッダーの高さ:', headerH, 'px');
// CSS変数にセット(CSS側から参照できるようにする)
document.documentElement.style.setProperty('--header-height', headerH + 'px');
});
CSS変数でヘッダー高さをCSSとJSで共有
JavaScriptで取得したヘッダー高さを
JavaScriptで取得したヘッダー高さを
--header-height などのCSS変数にセットすると、CSSの padding-top: var(--header-height) などで参照できます。JSとCSSの値を一元管理でき、メンテナンス性が上がります。CSS scroll-margin-top で解決する(最も簡単)
Modern CSS の scroll-margin-top を使うと、jQueryなしでジャンプ先の位置を調整できます。
/* ヘッダーが60pxの場合 */
:target {
scroll-margin-top: 60px;
}
/* CSS変数を使う場合 */
:target {
scroll-margin-top: var(--header-height, 60px);
}
:targetセレクターは#id でジャンプした要素に適用
:target 疑似クラスはURLの #section-id で指定された要素にマッチします。scroll-margin-top は全モダンブラウザで対応しており、最もシンプルな解決策です。jQueryでページ内リンクのスクロールを補正する
$(function () {
// ページ内リンク(#始まり)のクリックをjQueryで制御
$('a[href^="#"]').on('click', function (e) {
var href = $(this).attr('href');
if (href === '#') return; // ページトップリンクはデフォルト動作
e.preventDefault();
var $target = $(href);
if ($target.length === 0) return; // 対象要素がなければスキップ
var headerH = $('#site-header').outerHeight();
var targetTop = $target.offset().top - headerH - 8; // 余白8px
$('html, body').animate({ scrollTop: targetTop }, 400);
});
});
ウィンドウリサイズ時にヘッダー高さを再取得する
スマホでは横・縦持ち切り替えでヘッダー高さが変わることがあります。また、CSSメディアクエリでヘッダーの高さが変わる場合も再取得が必要です。
function debounce(fn, delay) {
var timer;
return function () {
clearTimeout(timer);
timer = setTimeout(fn, delay);
};
}
$(function () {
function updateHeaderHeight() {
var h = $('#site-header').outerHeight();
document.documentElement.style.setProperty('--header-height', h + 'px');
$('body').css('padding-top', h); // bodyのpaddingも更新
}
$(window).on('resize', debounce(updateHeaderHeight, 200));
updateHeaderHeight(); // 初回実行
});
bodyにpadding-topを追加してコンテンツが隠れないようにする
$(function () {
var headerH = $('#site-header').outerHeight();
// bodyにpaddingを追加して固定ヘッダー分のスペースを確保
$('body').css('padding-top', headerH);
// レスポンシブ: ヘッダーがfixedの場合のみpadding付加
function adjustPadding() {
var $header = $('#site-header');
var isFixed = $header.css('position') === 'fixed' ||
$header.css('position') === 'sticky';
$('body').css('padding-top', isFixed ? $header.outerHeight() : 0);
}
$(window).on('resize', debounce(adjustPadding, 200));
adjustPadding();
});
まとめ
固定ヘッダーとコンテンツ位置調整のポイントをまとめます。
- 高さ取得:
$("#header").outerHeight() - CSSのみ解決:
:target { scroll-margin-top: 60px }(最もシンプル) - jQueryスクロール補正: offset().top からヘッダー高さを引く
- CSS変数で共有:
document.documentElement.style.setProperty("--header-height", h+"px") - レスポンシブ: debounceで resize 時に再取得
関連記事: スムーズスクロール完全ガイド / 指定した要素の幅・高さを取得する完全ガイド
よくある質問(FAQ)
Qページ読み込み時のアンカーリンクでも補正したいです。
AURLに最初から
#section が含まれている場合は、ページ読み込み後にスクロール位置を再調整します:if (location.hash) { var $t = $(location.hash); $("html,body").scrollTop($t.offset().top - headerH - 8); }最も簡単な対応は :target { scroll-margin-top: var(--header-height) } のCSS解決です。Qスクロール中にヘッダーが小さくなります(ヘッダーシュリンク)。
Aスクロールでヘッダーの高さが変わる場合は、スクロールイベントでも高さを再取得する必要があります。または CSS変数に縮小後のヘッダー高さを設定してCSSで管理する方法もあります。Cocoonテーマなどを使っている場合はテーマのヘッダー設定も確認してください。
Qアンカーリンクの補正がWordPressで効きません。
AWordPressでは他のプラグインやテーマが
a[href^="#"] のスクロールを既に制御している場合があります。e.stopPropagation() を追加するか、先に定義されたイベントを .off("click") で解除してから再定義してください。また、Cocoonテーマにはスムーズスクロール機能が内蔵されています。Qモバイルのみヘッダーが固定でPCは固定でない場合はどうすれば?
ACSSの
position プロパティを取得してfixedかどうかを判断します:if ($("#header").css("position") === "fixed") { ... }またはウィンドウ幅で条件分岐してください:if ($(window).width() < 768) { ... }Q目次リンクのスクロール補正はどこに書けばよいですか?
Aテーマの
functions.php で wp_enqueue_script() を使い、カスタムJSファイルを読み込む方法が推奨です。または子テーマの style.css の末尾に <style> タグでCSSのscroll-margin-topを追加する方法もシンプルです。

