ページ内リンクをスムーズスクロールで行いたい場合はどのようにすればよいでのしょうか?
jQueryを利用すれば簡単に対応できますが、非jQueryの案件ですと悩みものです。
筆者は12年前にjQuery非依存のスムーズスクロールのJavaScriptライブラリ「smoothScroll.js」をリリースしていますがお世辞にも今の時代に利用するのに適したライブラリではありません。
今回は2019年に適したスムーズスクロールの方法をご紹介いたします。
CSSでスムーズスクロール
もっとも簡単に利用できるのはCSSのみでスムーズスクロールを実装する方法です。
html要素に scroll-behavior: smooth;
を適用することでページ内リンクがスムーズスクロールに変化します。
html{
scroll-behavior: smooth;
}
以下は実際に適用した簡単なサンプルです。
すごく便利ですが対応ブラウザが少し限定的です。主なブラウザではChrome(Android含む)とFirefoxのみで、IE11はもちろんのことMS Edge、Safariにも対応していません。プログレッシブ エンハンスメントとして対応ブラウザにのみ適用できる要件でないと利用は難しいでしょう。
参考:scroll-behavior – CSS: カスケーディングスタイルシート | MDN
また、すべてのスクロールがスムーズスクロールに変わってしまうのでSPAのようにページ遷移ごとにスクロール位置の調整が必要な場合にスムーズスクロールになってしまい微妙な挙動になってしまいます。
JavaScriptでスムーズスクロール
CSSでの制御が要件に合わない場合はJavaScriptで制御することも可能です。
scrollIntoViewでスクロール
scrollIntoView
は指定した要素が画面内に収まるようにスクロールさせるためのメソッドです。
スクロール位置に設定したい要素に対して実行でき、オプションで behavior を smooth に、 block を start に設定することで先程のCSSと同じような挙動にすることができます。
Element.scrollIntoView({
behavior: 'smooth',
block: 'start'
})
以下はclass属性「js-smooth-scroll」がある要素がクリックされた場合にスムーズスクロールされるようにしたサンプルです。
こちらも対応ブラウザが限定的です。主なブラウザではChrome(Android含む)とFirefoxのみで、IE11はもちろんのことMS Edge、Safariにも対応していません。(メソッド自体は存在するのでエラーにはならないのですがオプションの指定が無視されます。)
参考: Element.scrollIntoView() – Web API | MDN
ただし、smooth scroll behavior polyfillというpolyfillパッケージが公開されておりこちらを読み込むことで以下のモダンブラウザでもスムーズスクロールが実現可能です。
- Safari 6+
- Internet Explorer 9+
- Microsoft Edge 12+
polyfill を利用するには npm よりパッケージのインストールを行い
npm install smoothscroll-polyfill
利用したい箇所で読み込んで実行するだけで上記のブラウザでbehaviorオプションが有効になります。
import smoothscroll from 'smoothscroll-polyfill';
smoothscroll.polyfill();
以下がpolyfillを読み込んだバージョンです。
多くのケースではこれで事足りるでしょう。
window.scrollでスクロール
scrollIntoView
では細かい制御ができません。例えば指定した要素の50px上の位置に移動したいなどといった対応ができません。
そういった場合は古くから利用されている window.scroll()
でスクロールを行います。
window.scroll()
でもbehaviorオプションが利用できるようになっておりスムーズにスクロールさせることが可能です。
例えば、以下のようにすると目的の要素の50px上部までスクロールして移動が可能です。
const targetElement = document.querySelector(mySelecor);
// 画面上部から要素までの距離
const rectTop = targetElement.getBoundingClientRect().top
// 現在のスクロール距離
const offsetTop = window.pageYOffset
// スクロール位置に持たせるバッファ
const buffer = 50
const top = rectTop + offsetTop - buffer
window.scrollTo({
top,
behavior: "smooth"
});
以下はclass属性「js-smooth-scroll」がある要素がクリックされた場合にスムーズスクロールされるようにしたサンプルです。
このように最近ではブラウザのネイティブの機能でスムーズスクロールが利用でき、対応していないブラウザでもpolyfillを導入することで可能になっていますのでこれらを利用するのがよいでしょう。
【告知】弊社のメンバーが執筆した書籍が発売されました!
弊社のメンバーが執筆した『初心者からちゃんとしたプロになる JavaScript基礎入門』が発売されました! JavaScriptの基礎からVue.jsまでをカバーしており、初学者から基本の復習をしたい方におすすめの1冊です。