jQueryを使わない案件でスムーズスクロールを実装する機会があったので、実装方法をメモ。
実装方法1
scrollTo()のオプションでbehavior: ‘smooth’を設定することで、スムーズスクロールが実装できるようです。
ページ内リンクを設定するリンク要素に対して.js-pagelinkを付与するようにします。
<ul> <li><a href="#section1" class="js-pagelink">セクション1</a></li> <li><a href="#section2" class="js-pagelink">セクション2</a></li> <li><a href="#section3" class="js-pagelink">セクション3</a></li> </ul> <section id="section1" class="section"> <h2>セクション1</h2> </section> <section id="section2" class="section"> <h2>セクション2</h2> </section> <section id="section3" class="section"> <h2>セクション3</h2> </section>
JavaScriptでスムーズスクロールの処理を実装します。
var pagelink = document.querySelectorAll('.js-pagelink'); for( var i = 0; i < pagelink.length; i++ ) { pagelink[i].addEventListener('click', smoothScroll, false); } function smoothScroll(e) { e.preventDefault(); // 遷移先の要素 var pagelinkId = e.target.hash; var pagelinkSection = document.querySelector(pagelinkId); // スクロール先の位置 var scrollPosition = window.pageYOffset + pagelinkSection.getBoundingClientRect().top; // スクロールで移動 window.scrollTo({ top: scrollPosition, behavior: "smooth" }); }
スムーズスクロールのデモページ
これでchrome,firefox,edgeは問題なかったのですが、safariとIEではうまく動作しませんでした。
実装方法2
先ほどの実装を修正して、safariとIE用に別途処理を追加する形にしてみます。
var pagelink = document.querySelectorAll('.js-pagelink'); /* scrollToのOptionsに対応しているかのどうかの判別 */ var smoothScrollType; if('scrollBehavior' in document.documentElement.style) { smoothScrollType = smoothScroll; } else { smoothScrollType = oldTypeSmoothScroll; } for( var i = 0; i < pagelink.length; i++ ) { pagelink[i].addEventListener('click', smoothScrollType, false); } /* scrollToのOptionsに対応している場合 */ function smoothScroll(e) { e.preventDefault(); // 遷移先の要素 var pagelinkId = e.target.hash; var pagelinkSection = document.querySelector(pagelinkId); // スクロール先の位置 var scrollPosition = window.pageYOffset + pagelinkSection.getBoundingClientRect().top; // スクロールで移動 window.scrollTo({ top: scrollPosition, behavior: "smooth" }); } /* scrollToのOptionsに対応していない場合 */ function oldTypeSmoothScroll(e) { e.preventDefault(); // スクロール速度の設定 var scrollSpeed = 300; var timerStep = 20; // 遷移先の要素 var pagelinkId = e.target.hash; var pagelinkSection = document.querySelector(pagelinkId); // スクロール先の位置 var scrollPosition = window.pageYOffset; var sectionPosition = pagelinkSection.getBoundingClientRect().top; var goalPosition = scrollPosition + sectionPosition; // スクロール量 var scrollStep = sectionPosition / (scrollSpeed / timerStep); var currentScroll = scrollPosition; // スクロールの実行 var smoothScrollTimer = setInterval(function() { // スクロール完了時 if(currentScroll >= goalPosition) { // スクロール位置を完了位置に設定 window.scrollTo(0, goalPosition); // タイマーのクリア clearInterval(smoothScrollTimer); } else { currentScroll += scrollStep; window.scrollTo(0, currentScroll); } }, timerStep); }
これでsafariやIEでもスムーズスクロールされるようになりました。
スムーズスクロールのデモページ2
oldTypeSmoothScroll()という関数を用意して、behavior: ‘smooth’に対応していない場合の処理を追加しています。
元の処理との出しわけは6行目の if(‘scrollBehavior’ in document.documentElement.style) で行っています。
実装方法3
behavior: ‘smooth’に対応するためのpolyfillがあるようなので、実装方法1に読み込みを追加してみます。
polyfillはこちらからインストールしてください。
インストール後、読み込みを追加します。
<script src="smoothscroll.js"></script>
これでsafariやIEでもbehavior: ‘smooth’が効くようになりました。
スムーズスクロールのデモページ3
コメントが承認されるまで時間がかかります。