(css) scroll-behavior と scroll-margin-top についてメモ

css の scroll-behaviorscroll-margin-top について検証したのでメモ。

経緯

Bootstrap 5 で何気なく検証をしていたら、特に何をしたわけでもないのに同一ページ内のアンカーリンクにアニメーション付きでスクロールしたので気になりました。

自前の JavaScript では何も記述していないプレーンな状態だったので、 Bootstrap 5 の JavaScript かと思ったのですが、該当の CDN からの読み込みの scriptタグ を削除しても動作したので「すわ css 側か?」となり調べてみることにしました。

調査結果

結果、 scroll-behaviorプロパティ に依るものと分かりました。具体的には、

html {
    scroll-behavior: smooth;
}

この記述でページ全体にスクロールアニメーションが付与されていました。

しかも調べてみると、別ページのアンカーリンクに遷移する場合は

  1. ページ遷移
  2. 遷移先のページでアンカーリンクまで自動的にアニメーション付きでスクロール

という挙動をすることが分かりました。

css で別ページのアンカーリンクまで対応しているのであれば、上述の挙動が気になる場合を除けばもはやこれ1つで済んでしまうのではないでしょうか……。

注意点としては、 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-topscroll-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

ネガティブマージョンとパディングの調整

scroll-margin-top

この記事を書いた人

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。