ページ内リンクのスムーズスクロールは色々なサイトで見かけるのですが、ブラウザバック時に元の位置ではなく前のページに戻ってしまうようになっていることが多いので、ブラウザバックに対応できないかを調べてみました。
サンプルコード
よくあるスムーズスクロールを実装してみます。
HTML
<nav class="nav"> <p>目次</p> <ul> <li><a href="#sec01">section01</a></li> <li><a href="#sec02">section02</a></li> <li><a href="#sec03">section03</a></li> <li><a href="#sec04">section04</a></li> <li><a href="#sec05">section05</a></li> </ul> </nav> <div class="contents"> <main> <section id="sec01" class="section"> <h1>section01</h1> </section> <section id="sec02" class="section"> <h1>section02</h1> </section> <section id="sec03" class="section"> <h1>section03</h1> </section> <section id="sec04" class="section"> <h1>section04</h1> </section> <section id="sec05" class="section"> <h1>section05</h1> </section> </main> </div>
JavaScript
$(function() { $('a[href ^= "#"]').click(function() { $('html,body').animate({ scrollTop: $($(this).attr('href')).offset().top }, 300); return false; }) });
return falseが入っているのでURLがハッシュ付きのもの書き換わらず、ブラウザ履歴に残らないためブラウザバックで前のページに遷移してしまいます。
スムーズスクロールのデモページ
History APIを使って、ハッシュ付きURLをブラウザ履歴に追加するようにしてみました。
JavaScript
$(function() { $('a[href ^= "#"]').click(function() { // URL書き換え window.history.pushState(null, null, $(this).attr('href')); $('html,body').animate({ scrollTop: $($(this).attr('href')).offset().top }, 300); return false; }) });
これで対応できるかと思ったのですが、IEとedgeで1回目がうまく動作しないようでした。
(1回目のページ内リンク→ブラウザバックでは元の位置に戻らないが、続けてもう一度ページ内リンク→ブラウザバックを行うと元の位置に戻る)
スムーズスクロールのデモページ2
最終的に、return falseを外してデフォルトのリンク処理は動作するようにして、そのうえでスムーズスクロールさせるようにしました。
JavaScript
$(function() { $('a[href ^= "#"]').click(function() { $('html,body').animate({ scrollTop: $($(this).attr('href')).offset().top }, 300); }) });
この場合でもIEとedgeでスムーズスクロールの挙動が少し怪しいですが、そこまで気にならないレベルなのでまあいいかなと思います。
スムーズスクロールのデモページ3
コメントが承認されるまで時間がかかります。