「ページ内のスムーススクロールができるようになりたい」と思い、JavaScriptやjQueryでの実装方法を調べようとしている方も多いと思います。
ただ、CSSだけで実現出来る「scroll-behavior」というプロパティがあるのをご存知ですか?
- CSSだけでスムーススクロールがカンタンに実装してみたい
- scroll-behaviorのデメリットを理解し、jsとの使い分けができるようになりたい
この記事を読んで、コーディングの幅を広げましょう!
scroll-behaviorとは
scroll-behaviorとは、ページ内リンクをクリックした際、該当箇所へ時間をかけてスクロールするイベント(スムーススクロール)を発生させるプロパティです。
scroll-behavior: smoothでスムーススクロール
scroll-behavior: smooth;
scroll-behaviorプロパティは、CSS1行だけでスムーススクロールが実現できます!
JavaScriptやライブラリのjQueryで実装する場合と比べて手軽なので、今後活用していきたいプロパティですね。
scroll-behaviorのブラウザ対応状況
主要なブラウザの最新版ではほとんどが対応してますが、一部注意が必要です。
Safariには注意が必要
Safariではバージョン15.4からのみscroll-behaviorプロパティに対応しています。
Appleの公式サイトによると、全iPhoneデバイスの内6%程度はiOS14以前のバージョン利用者がいるようです。
国内のスマホはAppleのシェアが半数以上を占めているため、取り入れる場合は少し注意した方がいいかもしれません。
scroll-behaviorプロパティの構文
scroll-behaviorプロパティの初期値はautoで、スクロールスピードを変えるためにはsmoothを指定します。
/* 即時に遷移する */
html {
scroll-behavior: auto;
}
/* ゆっくり遷移する */
html {
scroll-behavior: smooth;
}
基本的にrootとなるhtmlタグに対して設定します。
ルート要素に指定することでビューポート(画面上)に適用されますが、bodyタグに指定してもビューポートには適用されません。
scroll-behaviorを使ったスムーススクロールのサンプル
上のサンプルの重要な部分のみ抜粋して解説します。
<header>
<nav>
<ul class="header-inner">
<li><a href="#section1">section1</a></li>
<li><a href="#section2">section2</a></li>
<li><a href="#section3">section3</a></li>
<li><a href="#section4">section4</a></li>
<li><a href="#section5">section5</a></li>
</ul>
</nav>
</header>
固定ヘッダーのリンク(aタグ)にはアンカーリンクを設定します。
<main>
<h2 id="section1" class="section">section1</h2>
<h2 id="section2" class="section">section2</h2>
<h2 id="section3" class="section">section3</h2>
<h2 id="section4" class="section">section4</h2>
<h2 id="section5" class="section">section5</h2>
<p class="back-btn"><a href="#">Topに戻る</a></p>
</main>
次に遷移先にidでアンカーリンク名を設定します。
また、ページ右下のボタンリンク(aタグ)にはアンカーリンクではなく#だけ設定してページトップを指定します。
html {
scroll-behavior: smooth;
}
デザイン部分は省略しますが(CodePenに記載あります)、CSSにはhtmlタグにscroll-vehavior: smoothを指定するだけです。
これだけでユーザーがページ内のリンクをクリックした際にスムーススクロールが実現できます。
scroll-behaviorの注意点
便利なscroll-behaviorプロパティですが注意点もあります。
すべてのページ内リンクがスムーススクロールになる
scroll-behaviorは文書のrootに設定するため、文書全体に対して制御がかかります。つまり、ページ内リンクはすべてスムーススクロールになります。
リンクによって挙動を設定できない点に注意しましょう。
移動速度の設定ができない
JavaScriptであればスクロールの移動スピードを指定できますが、scroll-behaviorプロパティでは速度を指定できません。
速度(イージング)はブラウザ依存となります。
遷移先の位置を指定できない
JavaScriptであれば移動先の位置を指定できますが、scroll-behaviorプロパティでは移動先の細かい位置は指定できません。
遷移先のブロックに対し、paddingやmarginなどで上方向に余白を設けることで調整する必要があります。
URLにアンカーリンクがつく
上はJavaScript(jQuery)で実装したスムーススクロールですが、URLは変わりません。
それに対し、scroll-behaviorプロパティで実装すると、上の画像のようにリンクをクリック時にURLにアンカーリンクが付与されます。
JavaScriptでURLの状態を取得するような機能がある場合、影響が出てしまう可能性はあります。
スクロール先がずれる時の対策
固定ヘッダーの場合、スクロール位置とヘッダーが被るなど、ズレが発生してしまうことがあります。
scroll-behaviorプロパティはスクロールするとアンカーポイントの位置をブラウザの一番上に表示しようとします。
対策していない場合、図のようにアンカーポイントを設定した部分がヘッダーの後ろに隠れて見えなくなってしまいます。
こちらの対策としてよく使われるのが、padding-top と margin-topのネガティブマージンで相殺する方法です。
.section {
margin-top: -80px;
padding-top: 80px;
}
この方法の場合、paddingで要素の大きさを広げる分、見た目上の余白もできてしまいます。
そこで使えるのが scroll-padding-top プロパティです。
.section {
scroll-margin-top: 80px; /* 追記 */
}
遷移先にscroll-margin-topプロパティと任意の値を指定すると、スクロールしたときにだけ適用する余白を指定できます。
画像ではヘッダー高さが80pxだったため、scroll-margin-topにも同じ値を指定します。
見た目上の余白は変わっていませんが、スクロール時のみ余白が確保されることでズレが解消できています。
scroll-behaviorの代替案
scroll-behaviorでは理想の動作を実装する事ができないかもしれません。そんな時に知っておきたい代替案を2つ紹介します。
scroll-behaviorのpolyfill
「scroll-behavior-polyfill」というパッケージが配布されています。古いバージョンのブラウザに対応するときに利用できるでしょう。
次のページからCDNのファイルのURLを確認することができます。
<script src="https://cdn.jsdelivr.net/npm/scroll-behavior-polyfill@2.0.13/dist/index.min.js"></script>
こちらがCDNのコードです。
使い方はGitHubにも記載がありますが、インストールをしてJavaScriptのファイルで呼び出すと利用できます。
また、「smooth scroll behavior polyfill」のページで動作を確認することもできます。
js(jQuery)で実装する方法
コード量だけで見ると、jQueryで実装する方法もカンタンです。
$(function () {
$('a[href^="#"]').click(function () {
var href = $(this).attr("href");
var target = $(href == "#" || href == "" ? 'html' : href);
var position = target.offset().top;
var speed = 500;
$("html, body").animate({
scrollTop: position
}, speed, "swing");
return false;
});
});
こちらの内容は以下記事で詳細に解説しています!
まとめ
scroll-vehavior:プロパティはいくつかの注意が必要なものの、CSSだけで手軽にスムーススクロールのアニメーションを加えることのできる便利なプロパティです。
手軽に実装したい場合は取り入れていきたいところ。
実務ではブラウザ要件やデメリットを確認し、問題なければ取り入れるようにしましょう!