スティッキーヘッダー(画面追従ヘッダー)は最近流行っていますが、ページ内や外部ページからアンカーリンクで遷移してきた場合に、スティッキーヘッダー分ずれてしまいます。通常は見出しにアンカーリンクを設定することが多いので、そのコンテンツの見出しが隠れてしまうので良くないですよね。
サーバーサイドで処理するために、アンカーリンク(#)ではなく、GETパラメータ(?key=value)を渡して対応しているサイトもいくつかあるようですが、外部のサイトからリンクを貼ってもらう場合など、こちらの意図通りにリンクされるかどうかはわかりません。できればWeb標準のアンカーリンク(#)で対応したいです。
そこで、この問題をJavaScriptで解決する方法をご紹介します。(スムーズスクロール対応)
お好きな所から読める目次
HTMLコード
HTMLは以下の構造を想定しています。
※要点のみ掲載
<body>
<header>ヘッダー</header>
<article>本文</article>
<footer>フッター</footer>
</body>
CSSでheaderタグを固定しています。画面スクロールするとheaderタグの箇所が画面上部に吸着したままスクロールされます。あとは本文のarticleエリアに見出しと文章を投入し、それらの見出しへのアンカーリンクをheaderエリア内にナビゲーションリンクとして配置します。
JavaScriptコード(要jQuery)
ポイントはDOMツリー生成直後に実行させることです。DOMツリー生成前だとオブジェクトの要素の取得に失敗してしまいます。よく見かける『window.onload』だと、HTMLの読み込み完了後に発火するのですが、『HTML読み込み→DOMツリー生成』と処理が走るため、DOMツリー生成前ではオブジェクトの要素取得ができません。
それに対応するために、『setTimeout(myFunc, 1000);』のように1秒間スリープを入れるなどの方法がありますが、これもその指定した秒数で必ずDOMツリーが生成できるとは限りません。かと言って多めに設定しても、ページの読み込み速度が落ちてしまうため、UX的にもあまり良くありません。
その点、『DOMContentLoaded』を使用すると、必ずDOMツリー生成後に発火してくれるので、最小タイムで最適なタイミングで実行できます。
【JavaScript】DOMツリー生成直後に発火するDOMContentLoaded
<script type="text/javascript">
// DOMツリー生成直後に実行する
document.addEventListener('DOMContentLoaded', function() {
// スティッキーヘッダーの高さを取得
var headerHeight = $('header').outerHeight();
// URLからハッシュ値を取得
var urlHash = location.hash;
// ハッシュ値があればターゲットへスムーズスクロールする
if(urlHash) {
$('body,html').stop().scrollTop(0);
var target = $(urlHash);
var position = target.offset().top - headerHeight;
$('body,html').stop().animate({scrollTop:position}, 500);
}
// aタグ内のアンカーリンクをクリックしたらスムーズスクロールする
$('a[href*="#"]').click(function() {
var href= $(this).attr("href").split('#')
;
var target = $("#"+href);
var position = target.offset().top - headerHeight;
$('body,html').stop().animate({scrollTop:position}, 500);
});
});
</script>
サンプルページ
実際の動作を確認できるサンプルページを用意しました。
さいごに
スティッキーヘッダーはこれから主流になっていくと思います。アンカーリンクのことは見落としがちなので、きちんと対応するようにしましょう。
