ヘッダーナビゲーションなどを固定するスタイルは良くみかけるデザインですよね。
ヘッダーをスクロールに追従させることで、ユーザーがわざわざページ上部に戻らなくてもすぐにナビゲーションにアクセスできるようになります。
スマホでの縦に長いページにはユーザービリティが向上する有用な手段です。また、ヘッダーナビゲーションにはメニューや検索フォームなど、重要な機能が含まれることが多いため、それらのアクセス性が向上します。
ヘッダーをページ上部に固定したり、下部にナビゲーションを固定するための方法にはposition:fixedを使って固定するのが一般的です。
position:fixedを使った時に手こずるのが、アンカーの位置がずれてしまう問題。
ページ内リンクにジャンプすると、リンク先が固定ヘッダーの下に隠れてしまいます。
See the Pen position:fixedでアンカーがずれる状態 by mixtaro (@mixtaro) on CodePen.
このアンカーがずれてしまうのを解決する方法で、従来からある方法とCSSでより簡単に解決できる方法を説明します。
ネガティブマージンとパディングを設定する
まずは従来から使われている固定したヘッダーの高さ分のネガティブマージンと、高さ相殺用のパディングを設定する方法です。
See the Pen position:fixedでアンカーがずれる margin/padding by mixtaro (@mixtaro) on CodePen.
/* 固定ヘッダー */
header{
position:fixed;
height:60px; /* 高さを指定しておく */
}
リンク先の要素に固定ヘッダーの高さ分のネガティブマージンとパディングを指定します。
h2[id^="header"]{
margin-top:-60px;
padding-top:60px;
}
scroll-margin-topプロパティを使用する
scroll-margin-topプロパティはCSS スクロールスナップというCSSの機能のうちの一つで、
CSS スクロールスナップ (CSS Scroll Snap) は CSS モジュールの一つで、スクロール操作の完了後にスクロールコンテナーのスクロールポートが終了するスクロール位置を強制する、スクロールスナップ位置を導入します。
MDN CSSスクロールスナップ
とMDNにあるようにスクロール時の挙動を制御してスクロール位置を特定の位置で止めたりできる機能です。
以前はブラウザによって未対応だったり、バグがあったりした見たいですが現在はちゃんと動いてくれるようになっています。
caniuse https://caniuse.com/mdn-css_properties_scroll-margin-top
See the Pen position:fixedでアンカーがずれる scroll-margin-top by mixtaro (@mixtaro) on CodePen.
使い方は先程と同様にアンカーのリンク先になる要素にscroll-margin-top
プロパティを設定し、ヘッダーの高さ分の余白を指定することで解決できます。
h2[id^="header"]{
scroll-margin-top:60px;
}
:target
セレクタ、カスタムプロパティを使った今時のやり方
:target
セレクタにスクロールマージンを指定すれば個別に対応する必要がなくなります。
:target {
scroll-margin-top: 60px;
}
さらにカスタムプロパティを作成しておけば、メンテナンス性も向上します。
:root {
--header-h: 60px;
}
:target {
scroll-margin-top: var(--header-h);
}
header {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: var(--header-h);
background-color: #624763;
color: #fff;
}
カスタムプロパティも最強です。
See the Pen position:fixedでアンカーがずれる :target selector by mixtaro (@mixtaro) on CodePen.
scroll-padding-topを使ってアンカーの位置を調整する
scroll-margin-topと同じようにscroll-padding-topプロパティを使ってアンカー位置を調整することができます。
See the Pen position:fixedでアンカーがずれる scroll-padding-top by mixtaro (@mixtaro) on CodePen.
html {
scroll-padding-top:var(--header-h);
}
scroll-padding-topの場合は適用対象が「スクロールコンテナー」となります。なのでリンク先要素に設定するのではなく、html要素にscroll-padding-topを指定します。
jQueryでヘッダー高さを取得しアンカーの位置を調整する方法
最後にCSSで解決できることが多くなったので使う機会は少ないかと思いますが、一応jQueryを使った解決方法も記載します。
See the Pen position:fixedでアンカーがずれる jQuery by mixtaro (@mixtaro) on CodePen.
$(function() {
$('a[href^="#"]').click(function() {
var headerHeight = $('header').outerHeight();
var href = $(this).attr('href');
var target = $(href == '#' || href == '' ? 'html' : href);
var position = target.offset().top - headerHeight;
$('html, body').animate({scrollTop: position}, 500, 'swing');
return false;
});
});
このコードでは、ヘッダーの高さを取得してアンカーの位置を調整しています。
以上、position:fixedで要素を固定した時にアンカーが隠れてしまうのを解決する方法を紹介しました。ここ数年でCSSだけでできることが大幅に増えたような気がします。