こんにちは!コーダーのゆうしです。
ページ内リンクをクリックしたときにスムーズにスクロールする「スムーススクロール」は、コーポレートサイトやLPでよく使われる実装のひとつです。ただ固定ヘッダーがあるサイトだと、リンク先の見出しがヘッダーの裏に隠れてしまうことがあります。この記事ではjQueryでスムーススクロールを実装しつつ、固定ヘッダー分の位置を調整する方法を解説します。
CSSだけでスムーススクロールを実装する方法
jQueryを使わずCSSだけで実装する方法もあります。<html> に以下を指定するだけです。
html {
scroll-behavior: smooth;
}シンプルで手軽ですが、スクロール速度の調整や固定ヘッダー分のオフセット指定が難しいのがデメリットです。細かい調整が必要な場合はjQueryで実装するほうが柔軟に対応できます。
jQueryでスムーススクロールを実装する
基本のコード
$(function () {
$('a[href^="#"]').click(function () {
var href = $(this).attr('href');
var target = $(href == '#' || href == '' ? 'html' : href);
var position = target.offset().top;
$('html, body').animate({ scrollTop: position }, 1000, 'swing');
return false;
});
});a[href^="#"] でページ内リンク(#から始まるリンク)をすべて対象にしています。クリックされたリンクのhref属性を取得して、対象要素の位置までアニメーションでスクロールします。
スクロール速度を変える
$('html, body').animate({ scrollTop: position }, 1000, 'swing');1000 の部分がスクロールにかかる時間(ミリ秒)です。小さくすると速く、大きくするとゆっくりになります。'swing' はイージングの種類で 'linear'(一定速度)に変えることもできます。
固定ヘッダー分の位置をずらす
固定ヘッダーがあると、スクロール先の見出しがヘッダーの裏に隠れてしまいます。headerHeight でヘッダーの高さ分だけ位置を引いて調整します。
$(function () {
var headerHeight = 100; // ヘッダーの高さ(px)を指定
$('a[href^="#"]').click(function () {
var href = $(this).attr('href');
var target = $(href == '#' || href == '' ? 'html' : href);
var position = target.offset().top - headerHeight;
$('html, body').animate({ scrollTop: position }, 1000, 'swing');
return false;
});
});headerHeight の 100 をヘッダーの実際の高さに変更してください。余白を少し多めに取りたい場合は ヘッダーの高さ + 30 くらいにすると見栄えが良くなることが多いです。
PCとスマホでオフセット量を変える
PCとスマホでヘッダーの高さが違う場合は、ウィンドウ幅で分岐させます。
$(function () {
var windowWidth = $(window).width();
var breakPoint = 767;
if (windowWidth <= breakPoint) {
// スマホ(767px以下)
var headerHeight = 80;
$('a[href^="#"]').click(function () {
var href = $(this).attr('href');
var target = $(href == '#' || href == '' ? 'html' : href);
var position = target.offset().top - headerHeight;
$('html, body').animate({ scrollTop: position }, 1000, 'swing');
return false;
});
} else {
// PC(768px以上)
var headerHeight = 130;
$('a[href^="#"]').click(function () {
var href = $(this).attr('href');
var target = $(href == '#' || href == '' ? 'html' : href);
var position = target.offset().top - headerHeight;
$('html, body').animate({ scrollTop: position }, 1000, 'swing');
return false;
});
}
});breakPoint のブレイクポイントと headerHeight の値はサイトに合わせて変更してください。
躓きやすいポイント
スクロールが動かない
jQueryが読み込まれていない場合に起こりやすいエラーです。コンソールに $ is not defined と表示される場合はjQueryの読み込みを確認してください。またjQueryのコードはjQueryの読み込みより後に書く必要があります。
ヘッダーの裏に隠れる
headerHeight の値がヘッダーの実際の高さより小さいと見出しがヘッダーの裏に隠れます。ブラウザの開発者ツールでヘッダーの高さを確認してから値を設定してください。
URLに#が残る
return false; を忘れると、クリック時にURLに #section が残ってしまいます。コードの末尾に return false; が入っているか確認してください。
スマホでリサイズ後に動きがおかしくなる
ウィンドウ幅の取得を $(function(){}) の中でやっているため、ページ読み込み時の幅で固定されます。画面回転などでリサイズが発生した場合は対応できないので、リサイズ対応が必要な場合は $(window).on('resize') と組み合わせるか、CSSの scroll-behavior: smooth と scroll-padding-top を使う方法も検討してみてください。
まとめ
jQueryでスムーススクロールを実装すると、スクロール速度の調整や固定ヘッダー分のオフセット指定を柔軟に設定できます。PCとスマホでヘッダーの高さが異なる場合もウィンドウ幅で分岐させることで対応できます。固定ヘッダーのサイトでは必ずオフセット調整を入れておくと、ユーザーが見やすくなります。
ご不明な点やコーディングのご依頼はお問い合わせからお気軽にどうぞ。

