css の scroll-behavior
と scroll-margin-top
について検証したのでメモ。
経緯
Bootstrap 5 で何気なく検証をしていたら、特に何をしたわけでもないのに同一ページ内のアンカーリンクにアニメーション付きでスクロールしたので気になりました。
自前の JavaScript では何も記述していないプレーンな状態だったので、 Bootstrap 5 の JavaScript かと思ったのですが、該当の CDN からの読み込みの script
タグ を削除しても動作したので「すわ css 側か?」となり調べてみることにしました。
調査結果
結果、 scroll-behavior
プロパティ に依るものと分かりました。具体的には、
html {
scroll-behavior: smooth;
}
この記述でページ全体にスクロールアニメーションが付与されていました。
しかも調べてみると、別ページのアンカーリンクに遷移する場合は
- ページ遷移
- 遷移先のページでアンカーリンクまで自動的にアニメーション付きでスクロール
という挙動をすることが分かりました。
css で別ページのアンカーリンクまで対応しているのであれば、上述の挙動が気になる場合を除けばもはやこれ1つで済んでしまうのではないでしょうか……。
- “scroll-behavior” | Can I use… Support tables for HTML5, CSS3, etc
- iOSのバージョンと Safariバージョンの対応表(2022\/4\/6 現在 – Qiita
注意点としては、 iOS Safari が15.4(2022/3/14リリース、2022/4/27記事執筆時点で最新版) のみサポートとなっているため、最新版以外の Safari のサポートが必要な場合は polyfill 等の代替手段を講じる必要性がありそうです。
PJAX 等のデフォルトではない遷移をした際の挙動については未検証なので何ともですが少し気になります。
それと、もう一点気になったのは Bootstrap のケースで言うとナビゲーションバーに .fixed-top
を付けていた場合。つまりナビゲーションバーが画面上部に固定表示で追従するパターンですね。
頻出するパターンですが、このケースでは工夫しないとアンカーリンク移動時にナビゲーションバーの裏側にコンテンツが隠れてしまうという課題がありました。
かつてはこれを margin-top: -80px; padding-top: 80px;
等とネガティブマージンとパディングで調整・相殺するテクニックを使っていましたが……。
scroll-margin-top
ここで兼ねてより目を付けていたのが scroll-margin-top
。 scroll-snap
と呼ばれるスクロール時に特定の位置で止めたり誘導するプロパティの1つで、上述のアンカーリンク遷移時にナビゲーションバーの裏側に隠れてしまう問題を解決する方法として利用できます。
.anchor-link {
scroll-margin-top: 80px;
}
これまで上述のようなネガティブマージョンとパディングの相殺や、あるいは before
疑似要素 を利用した方法で調整していた手間が、上述の通り1行指定するだけで解決できます。
css変数を使用するならば、
:root {
/* 変数定義 */
--navbar-height: 80px;
}
html {
/* スムーススクロール */
scroll-behavior: smooth;
}
.header {
/* ナビゲーションバーを上部固定表示 */
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 10;
/* css変数を使用して高さを指定 */
height: var(--navbar-height);
}
.main {
/* スクロール可能なコンテンツ領域の上端部分はめり込むのでここは普通に margin-top でナビゲーションバー分下げる。css変数使用。 */
margin-top: var(--navbar-height);
}
.anchor-link {
/* アンカーリンクが裏側に隠れるのを抑止。css変数使用。 */
scroll-margin-top: var(--navbar-height);
}
このようなイメージですね。
ちなみにこちらは iOS Safari 14.7 以降で有効ですが、やはりそこそこ新しめの Safari である必要があるので、こちらもケースによっては注意が必要そうです。
参考
scroll-behavior
- CSSだけでも実装できる!ページ内アンカーやページ上部にアニメーションでスクロールさせるCSS, JavaScriptのまとめ | コリス
- CSSでページ内リンクをなめらかにスクロールする|web design-havin’ a coffee break|珈琲とウェブデザイン
- “scroll-behavior” | Can I use… Support tables for HTML5, CSS3, etc
- iOSのバージョンと Safariバージョンの対応表(2022\/4\/6 現在 – Qiita
ネガティブマージョンとパディングの調整
scroll-margin-top
- アンカーリンクの遷移先が隠れる…。追従ヘッダーの重なりを回避するCSS | 会津ラボ
- アンカーリンクのズレをscroll-snapを使って直せるか試してみた – arms inc. Engineers’ Blog
- scroll-margin-top でヘッダー固定されたページのアンカーリンクの座標を調整する | ホワイトボードオフィシャルブログ
- 【追記: Safariでも動くようになった!】scroll-margin-topがsafariでうまく効かない問題と現状のワークアラウンド
- scroll-margin-top – CSS: カスケーディングスタイルシート | MDN
- “scroll-margin-top” | Can I use… Support tables for HTML5, CSS3, etc