[JavaScript] スムーススクロールを実装する方法|固定ヘッダー対応・ページトップボタンのフェード表示
ページ内リンクやページトップボタンにスムーススクロールを実装すると、ユーザーが快適にページ内を移動できるようになります。
この記事では、JavaScriptを使って以下を実現する方法を紹介します。
- ページトップボタンやページ内リンクをスムーススクロールさせる
- 固定ヘッダーによるスクロール位置のずれを防ぐ
- 一定量スクロールしたらページトップボタンを表示する
- ページ上部へ戻ったらページトップボタンを非表示にする
完成イメージ
今回実装するサンプルでは、以下の動作を実現しています。
- アンカーリンクをクリックするとスムーススクロールする
href="#"でページ上部へ戻る- 固定ヘッダーがある場合でもリンク先が隠れない
- 一定量スクロールするとページトップボタンが表示される
- ページ上部へ戻ると自動的に非表示になる
▼Codepen
See the Pen [JavaScript] ページトップボタン実装|スムーススクロール・固定ヘッダー・フェード表示対応 by mkl may (@mkl-may) on CodePen.
ページトップボタンやページ内リンクをスムーススクロールさせる
まずはアンカーリンクをクリックした際にスムーススクロールする処理を実装します。
window.scrollTo({
top: targetPosition,
behavior: 'smooth'
});
behavior: 'smooth' を指定することで、リンク先までなめらかにスクロールできます。
今回のサンプルでは、
const smoothScrollLinks =
document.querySelectorAll('a[href^="#"]');
としているため、
<a href="#section01">見出しへ移動</a>
<a href="#">ページ上部へ戻る</a>
のようなページ内リンクをまとめて処理できます。
固定ヘッダーがある場合のリンク位置のずれ対応
ヘッダーを position: fixed; で固定している場合、スクロール先の見出しがヘッダーの裏に隠れてしまうことがあります。
今回のコードではヘッダーの高さを取得し、スクロール位置を補正しています。
const headerHeight =
header?.offsetHeight ?? 0;
const isFixed =
header &&
getComputedStyle(header).position === 'fixed';
そしてスクロール時にヘッダー分の高さを差し引きます。
top: isFixed
? targetPosition - headerHeight
: targetPosition
これにより、リンク先のコンテンツがヘッダーに隠れず表示されます。
※ このサンプルは position: fixed; のヘッダーを想定しています。
ページトップボタンを一定の高さスクロールしたら表示する
ページトップボタンを常時表示するのではなく、ある程度スクロールしたタイミングで表示させます。
今回のサンプルでは以下の条件で表示を切り替えています。
const isActive =
window.scrollY > 100;
スクロール量が100pxを超えた場合に is-show クラスを付与します。
scrollFade?.classList.toggle(
'is-show',
isActive
);
100pxの部分はサイトに合わせて調整してください。
ページ上部へ戻ったらページトップボタンを非表示にする
ページ上部ではページトップボタンを表示する必要がないため、自動的に非表示にします。
先ほどと同じ処理で、スクロール量が100px以下になると is-show クラスが削除されます。
scrollFade?.classList.toggle(
'is-show',
isActive
);
CSS側では以下のように制御すると自然な表示になります。
.pagetop {
opacity: 0;
visibility: hidden;
transition: .3s;
}
.pagetop.is-show {
opacity: 1;
visibility: visible;
}
フェードイン・フェードアウトさせることで、違和感のない表示切り替えを実現できます。
まとめ
JavaScriptを利用すると、ページトップボタンやページ内リンクにスムーススクロールを簡単に実装できます。
ページの操作性やユーザビリティ向上につながるため、ブログやコーポレートサイトなど幅広いサイトで活用できる実装です。
![MARKLEAPS[マークリープス]](https://markleaps.com/blog/wp-content/themes/mkl/images/00_logo.png)