アンカーリンクのズレをscroll-snapを使って直せるか試してみた

こんにちは、中村です。
以前コリスさんの記事で紹介されていたscroll-snapのscroll-paddingを使った「ページ内リンクが固定ヘッダと重なって隠れる問題を解決するCSSのテクニック」が気になっていたので、今どうなっているのか確認してみました。
記事の時点ではまだChromeだけで、バグもあったようです。

2023/9/6追記:もっと簡単に解決できる方法は下記の記事をご覧ください。

tech.arms-soft.co.jp

解消したい現象について

アンカーリンクで遷移した時に、遷移先の要素と表示を固定した要素の位置が重なる、というもの。
ヘッダを固定した時によく起こる現象です。

対策としてはjsでスクロール位置を調整するか、CSSのpadding-topmargin-topで遷移先の開始位置をヘッダーの高さ分調整するのが一般的な手法です。
紹介されている手法はCSSのscroll-snapのうちの、scroll-padding-topを使った新しい手法になります。
jsを使わず、スタイルをリンク先の要素ごとに適用する必要もないのでこれができると簡単で良いなと思います。

scroll-snapとは?

スクロール時に特定の位置で止めたり誘導するプロパティです。
参考:CSS スクロールスナップ

スナップさせたい要素の親にscroll-snap-typeを指定

スクロールの方向と止まり方を指定します。
横方向はx、縦方向はy
厳密に止めたい場合はmandatory、誘導する程度の場合はproximityを指定します。

スナップさせたい要素にscroll-snap-alignを指定

その要素のどこにスナップするか、start, center, endのいずれかを指定します。

試してみた

See the Pen scroll-snap:scroll-padding-topによるページ内リンクのズレ解消 by Nakamura (@takayo-nakamura) on CodePen.

firefoxでも期待してる通りの位置にスクロールされるようになりました。
Chromeのhtmlのバグも解消されていましたが、他のブラウザではうまく動作しませんでした。

画面サイズいっぱいのwrapper要素を作ってscroll-snapを当ててみた

See the Pen scroll-snapによるアンカーリンクのズレ調整(wrapper編) by Nakamura (@takayo-nakamura) on CodePen.

scroll-snapコンテナ内にあるときはどうか、という検証でしたがこちらも同じ状態でした。
※Safariはスクロール時のスナップは効きますがアンカーリンクで遷移した時はズレます。

また、スナップさせた時の注意点があります。
Section01へ遷移したあと、その上へスクロールしてもSection01へスナップされるのでページトップへ戻れなくなりました。
こういうところも考慮しないといけないので使う時は注意が必要です。
アンカーリンクのズレ問題に対してはスナップさせずにscroll-padding-topだけ効かせたいのですがここがうまく機能しなかったのは残念です。

まとめ

scroll-snapは横スクロールでカルーセルのような動きを付けたい時になどに便利そうですね。 写真を複数見せたいレスポンシブページなどでスマホの表示ではよく横スクロールにするので、要素の始まりでピタッと止まってくれると心地よい動きになると思います。 使い方・対応状況は随時追っていきます。

今回、対応状況を確認しながら固定ヘッダそのものについても考えた方が良いなと思いました。
固定するのはナビゲーションの開閉ボタンだけで良い場合も多いです。
対応方法を考えるのはもちろん、使いやすい表現についても考えていきたいと思います。