固定ヘッダーの高さを考慮したスムーススクロール|jQueryでページ内リンクを調整する方法
Webサイトでは、ページ内のリンクをクリックしたときに、指定したセクションまで滑らかにスクロールする「スムーススクロール」がよく使われます。
例えば、
- 「詳しく見る」をクリックして該当セクションへ移動する
- ページ上部のメニューから各セクションへ移動する
- 「お問い合わせ」ボタンからお問い合わせフォームへ移動する
- 目次からページ内の見出しへ移動する
といった場面で利用できます。
しかし、ヘッダーを画面上部に固定しているWebサイトでは、通常のスムーススクロールを実装すると、スクロール先のコンテンツが固定ヘッダーの下に隠れてしまうことがあります。
そこで今回は、jQueryを使って固定表示しているヘッダーの高さを取得し、その高さを考慮してスクロール位置を調整する方法を紹介します。
固定ヘッダーがあるとコンテンツが隠れてしまう
まず、一般的なページ内リンクでは、以下のようにidを指定してリンク先を設定します。
<a href="#about">詳しく見る</a>
<section id="about">
<h2>About</h2>
<p>ここがスクロール先です。</p>
</section>
この状態で#aboutへスムーススクロールさせると、基本的にはid="about"が付いている要素の位置までスクロールします。
しかし、例えばヘッダーが、
header {
position: fixed;
top: 0;
}
のように固定表示されている場合、スクロール後にヘッダーとコンテンツが重なってしまうことがあります。
そこで、スクロール先の位置からヘッダーの高さ分だけ上へ移動させることで、この問題を解決します。
ヘッダーの高さを考慮したスムーススクロール
今回使用するjQueryのコードはこちらです。
jQuery(document).ready(function() {
// <header>の高さを取得
const headerHeight = $('header').outerHeight();
// ページ内スクロール
$('a[href^="#"]').click(function () {
const speed = 600;
let href = $(this).attr("href");
let target = $(href == "#" || href == "" ? "html" : href);
// スクロール先の位置を取得し、<header>の高さを考慮して補正
let position = target.offset().top - headerHeight;
$("body,html").animate({ scrollTop: position }, speed, "swing");
return false;
});
});
このコードでは、
- ヘッダーの高さを取得する
- ページ内リンクがクリックされたことを検出する
- リンク先の位置を取得する
- ヘッダーの高さを引いてスクロール位置を補正する
- 指定した位置まで滑らかにスクロールする
という処理を行っています。
jQueryを読み込んでいることを確認する
今回のコードはjQueryを使用しているため、サイトでjQueryが利用できる状態になっている必要があります。
WordPressではテーマやプラグインなどによってjQueryが読み込まれているケースもありますが、使用している環境によって異なります。
ブラウザのコンソールに、
$ is not defined
などのエラーが表示される場合は、jQueryが正しく読み込まれているか確認してください。
ドキュメントの読み込み完了後に処理する
最初の部分では、
jQuery(document).ready(function() {
と記述しています。
これは、HTMLのDOMが読み込まれた後にJavaScriptを実行するための記述です。
ページ内のHTML要素が存在する状態になってから処理を実行することで、ヘッダーやリンクなどの要素を正しく取得できます。
ヘッダーの高さを取得する
次に、
const headerHeight = $('header').outerHeight();
でヘッダーの高さを取得しています。
outerHeight()は、要素の高さに加えて、paddingやborderなども含めた外側の高さを取得するjQueryのメソッドです。
例えばヘッダーの高さが80pxだった場合、
headerHeight = 80
という値になります。
この値を後ほどスクロール位置の調整に利用します。
ページ内リンクを取得する
次に、
$('a[href^="#"]').click(function () {
としています。
ここでは、href属性が#から始まるaタグを取得しています。
例えば、
<a href="#about">About</a>
<a href="#service">Service</a>
<a href="#contact">Contact</a>
などが対象になります。
href^="#"の^=は、「指定した文字列で始まる」という意味です。
そのため、
#about
#service
#contact
のようなページ内リンクをまとめて対象にできます。
クリックされたリンク先を取得する
続いて、
const speed = 600;
let href = $(this).attr("href");
let target = $(href == "#" || href == "" ? "html" : href);
としています。
const speed = 600;
const speed = 600;
は、スクロールアニメーションの速度を指定しています。
単位はミリ秒なので、600の場合は0.6秒です。
例えば、
const speed = 1000;
とすれば1秒かけてスクロールします。
$(this).attr("href")
let href = $(this).attr("href");
では、クリックされたリンクのhref属性を取得しています。
例えば、
<a href="#contact">お問い合わせ</a>
をクリックした場合、
href = "#contact"
となります。
スクロール先を取得する
let target = $(href == "#" || href == "" ? "html" : href);
では、取得したhrefをもとにスクロール先を指定しています。
hrefが#または空の場合はhtmlを対象とし、それ以外の場合は指定されたIDを持つ要素を対象にします。
ヘッダーの高さ分だけスクロール位置を補正する
今回のコードで最も重要なのが、この部分です。
let position = target.offset().top - headerHeight;
target.offset().topで、スクロール先となる要素のページ上部からの位置を取得します。
例えば、スクロール先がページ上部から1000pxの位置にあり、固定ヘッダーの高さが80pxだった場合、
1000px - 80px = 920px
となります。
つまり、1000pxまでスクロールするのではなく、920pxまでスクロールすることで、ヘッダーの下に隠れずにコンテンツを表示できるという仕組みです。
イメージすると、
通常のスクロール
1000px → コンテンツがヘッダーと重なる
ヘッダーの高さを考慮
1000px - 80px = 920px
↓
コンテンツがヘッダーの下に隠れない
という違いになります。
固定ヘッダーの高さを考慮したスムーススクロールでは、この「スクロール先の位置からヘッダーの高さを引く」という考え方がポイントです。
スムーススクロールを実行する
最後に、
$("body,html").animate({ scrollTop: position }, speed, "swing");
return false;
でスクロールを実行します。
animate()
$("body,html").animate({
scrollTop: position
}, speed, "swing");
によって、指定した位置まで滑らかにスクロールします。
ここでは、
position:スクロール先speed:スクロール速度swing:アニメーションの動き方
を指定しています。
return false
return false;
は、リンクをクリックしたときにブラウザが通常行うページ内リンクへのジャンプをキャンセルするために使用しています。
これによって、通常の瞬間的なページ内移動ではなく、jQueryのアニメーションによるスムーススクロールが実行されます。
スクロール速度を変更する
スクロール速度は、
const speed = 600;
の数値を変更することで調整できます。
例えば、
const speed = 300;
とすれば、より素早くスクロールします。
反対に、
const speed = 1000;
とすれば、ゆっくりスクロールします。
サイトのデザインやページの長さに合わせて、ユーザーが違和感を感じない速度に調整するとよいでしょう。
ヘッダーの高さがPCとスマートフォンで違う場合
実際のWebサイトでは、PCとスマートフォンでヘッダーの高さが異なることがあります。
例えば、
PC:80px
スマートフォン:60px
のようなケースです。
今回のコードではページ読み込み時に、
const headerHeight = $('header').outerHeight();
としてヘッダーの高さを取得しているため、ページ読み込み時点のヘッダーサイズを基準にしています。
レスポンシブデザインによって画面幅に応じてヘッダーの高さが変化するサイトでは、より柔軟に対応するため、クリック時にヘッダーの高さを取得する方法もあります。
例えば、
let position = target.offset().top - $('header').outerHeight();
とすれば、リンクをクリックしたタイミングでヘッダーの高さを取得できます。
ヘッダーの高さが画面幅によって変わるサイトでは、このような方法も検討できます。
WordPressで使用する場合の注意点
WordPressサイトで今回のコードを使用する場合、テーマやプラグインによってページ内リンクの動作が独自に設定されている場合があります。
特に、
- WordPressテーマ側ですでにスムーススクロールが設定されている
- JavaScriptでページ内リンクを制御している
- jQueryを別の処理でも使用している
- ヘッダーの高さがレスポンシブで変化する
- ハンバーガーメニューなどでヘッダーの構造が変わる
といった場合は、コードを追加するだけでは正常に動作しないことがあります。
既存サイトへ実装する場合は、現在のJavaScriptやテーマの仕様を確認したうえで追加することが重要です。
また、ページ内リンクのすべてを対象にする必要がない場合は、
$('a[href^="#"]')
のようにサイト全体のアンカーリンクをまとめて対象にするのではなく、特定のクラスを付けたリンクだけを対象にする方法もあります。
例えば、
<a href="#contact" class="smooth-scroll">お問い合わせ</a>
として、
$('.smooth-scroll').click(function () {
とすれば、.smooth-scrollが付いたリンクだけを対象にできます。
既存サイトへの実装では、こちらのほうが他のリンクへの影響を抑えやすい場合があります。
まとめ
今回は、固定ヘッダーの高さを考慮してページ内をスムーススクロールさせるjQueryコードを紹介しました。
通常のページ内リンクでは、スクロール先のコンテンツが固定ヘッダーの下に隠れてしまうことがあります。
その場合は、
let position = target.offset().top - headerHeight;
のように、スクロール先の位置からヘッダーの高さを引いて位置を補正することで対応できます。
今回のポイントをまとめると、
outerHeight()でヘッダーの高さを取得する- ページ内リンクをクリックしたときに処理を実行する
offset().topでスクロール先の位置を取得する- ヘッダーの高さを引いてスクロール位置を補正する
animate()で滑らかにスクロールさせる- PCとスマートフォンでヘッダーの高さが異なる場合は注意する
- 既存サイトではテーマや他のJavaScriptとの競合を確認する
という仕組みです。
固定ヘッダーを使用しているWordPressサイトで、「ページ内リンクをクリックすると見出しがヘッダーに隠れてしまう」「スムーススクロールの位置を調整したい」といった場合に活用できます。
また、WordPressサイトではテーマやプラグインによって既にJavaScriptが設定されている場合もあるため、既存のコードとの競合には注意が必要です。
ホームページのJavaScript・jQueryの修正や、ページ内リンクの不具合、表示・動作トラブルなどでお困りの場合も対応しています。
365日対応・8:00〜23:00対応・最短即日対応で、原因が分からないホームページの不具合から、ちょっとしたコード修正まで対応しています。





