ページに目次をつけて、項目を押したらスクロールする
ものすごい小さい話ですが、毎回忘れてしまうのでメモします。
$('html,body').animate({ scrollTop: window.pageYOffset + target.getBoundingClientRect().top - 8 // 要素がブラウザ上部ぴったりになるので少し隙間をあけたり }, 500, 'swing');
まずwindow.pageYOffset
について、これはwindow.scrollY
のエイリアスだそうです。ページの一番上を0として、どのくらい下にスクロールしているかのピクセル値を返します。
次にelement.getBoundingClientRect().top
ですが、現在クライアントが見ている画面の上端を0として、そこからどれくらい要素が離れているかをピクセル値で返します。例えば要素をスクロールして通り過ぎていたら、負の値が返ってきます。
つまり、ページの一番上から現在表示している画面上端までの距離
と現在表示している画面上端から要素までの距離
を足すことでページの一番上から要素までの距離
を計算しているということになります。(多分絵で描くとわかりやすい???)
ページの一番上から現在表示している画面上端までの距離
現在表示している画面上端から要素までの距離
まとめ
多分覚えたのでもう忘れないはずです。ぶっちゃけていうとすでにここに書いてありました。。。
おまけ
デモです。
See the Pen MEbNmj by ushumpei(@ushumpei) on CodePen.
一枚にまとめたやつ
<html> <head> <style type="text/css"> .container { display: flex; flex-direction: row; justify-content: space-between; } .menu { background-color: #eee; display: flex; flex-direction: column; flex: 1; height: 120px; justify-content: space-around; padding: 8px; position: sticky; top: 8px; } .content { display: flex; flex-direction: column; flex: 3; justify-content: space-between; margin-left: 8px; } .section { height: 100vh; } .section > h1 { background-color: #eee; padding: 8px; margin-top: 0; } </style> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script> window.addEventListener('load', function() { var menuItems = Array.from(document.getElementsByClassName('menu-item')); var sections = Array.from(document.getElementsByClassName('section')); menuItems.forEach(function(item, i) { var target = sections[i]; item.addEventListener('click', function() { $('html,body').animate({ scrollTop: window.pageYOffset + target.getBoundingClientRect().top - 8 // 要素がブラウザ上部ぴったりになるので少し隙間をあけました }, 500, 'swing'); }); }); }); </script> </head> <body> <div class="container"> <div class="menu"> <a href="#" class="menu-item">section1</a> <a href="#" class="menu-item">section2</a> <a href="#" class="menu-item">section3</a> <a href="#" class="menu-item">section4</a> <a href="#" class="menu-item">section5</a> </div> <div class="content"> <div class="section"><h1>section1</h1></div> <div class="section"><h1>section2</h1></div> <div class="section"><h1>section3</h1></div> <div class="section"><h1>section4</h1></div> <div class="section"><h1>section5</h1></div> </div> </div> </body> </html>