【CSS&jQuery】固定ヘッダー時アンカーリンクの位置を調整する方法

アンカーリンクを使ってページ内リンクを行う最、ヘッダーを固定にしていると思い通りの動きをしてくれないことがあります。

これは、アンカーリンクのジャンプ先がブラウザ上部を基点に表示されるためです。

ヘッダーは固定のままにしたいですが、スクロールするコンテンツが隠れてしまうのは避けたいところ。コンテンツがヘッダーの高さ分下に表示されればちょうどいいですよね。

これを解消する方法として「CSSに記述する方法」と「jQueryを使う方法」があります。
内容的には比較的易しめなものですが、アンカーリンクがずれてしまう現象って割と発生しやすいものかなと思いましたので、今回のブログで取り上げていこうと思います。

基本の記述

まず、ページ内でリンクさせたい場合の基本的な記述について簡単に説明。 リンク先までジャンプさせたい要素には

<a href="#●●">テキスト</a>

を記述し、ページ内でジャンプさせたい場所に

<div id="●●"></div>

を記述。ちなみに、違うページの該当箇所に飛ばしたい場合は

<a href="xxxx.html#●●">ページ内リンク</a>

と、ファイル名を前述すればOKです。

アンカーリンクのジャンプ先が固定ヘッダーと被ってしまう・・・こんなときは?

ヘッダーの高さは100px、「position:fixed」でページtopに固定している前提で解説していきます。

<header>
    <nav>
        <a href="#contA">Content A</a>
        <a href="#contB">Content B</a>
        <a href="#contC">Content C</a>
        <a href="#contD">Content D</a>
    </nav>
</header>

    <!-- Contents A -->
    <div id="contA">
        <!-- ↓↓ 内容が入ります ↓↓ -->
        <h2>Contents A</h2>
        <p>テキストテキストテキストテキストテキストテキストテキスト</p>
    </div>

    <!-- Contents B -->
    <div id="contB">
        <!-- ↓↓ 内容が入ります ↓↓ -->
        <h2>Contents B</h2>
        <p>テキストテキストテキストテキストテキストテキストテキスト</p>
    </div>

    <!-- Contents C -->
    <div id="contC">
        <!-- ↓↓ 内容が入ります ↓↓ -->
        <h2>Contents C</h2>
        <p>テキストテキストテキストテキストテキストテキストテキスト</p>
    </div>

    <!-- Contents D -->
    <div id="contD">
        <!-- ↓↓ 内容が入ります ↓↓ -->
        <h2>Contents D</h2>
        <p>テキストテキストテキストテキストテキストテキストテキスト</p>
    </div>

<footer>
    <!-- ヘッダーの内容が入ります -->
</footer>

CSSを使って解決する方法

CSSでヘッダーの高さを確保するには、アンカーリンクのジャンプ先の要素となる部分に、「padding」と「margin」にヘッダーの高さ(今回の場合は100px)を指定し高さを相殺するためのclassを付与してあげましょう。

<div class="contents">
    <!-- Contents A -->
    <div id="contA" class="contents_inner">
        <!-- ↓↓ 内容が入ります ↓↓ -->
        <h2>Contents A</h2>
        <p>テキストテキストテキストテキストテキストテキストテキスト</p>
    </div>

    <!-- Contents B -->
    <div id="contB" class="contents_inner">
        <!-- ↓↓ 内容が入ります ↓↓ -->
        <h2>Contents B</h2>
        <p>テキストテキストテキストテキストテキストテキストテキスト</p>
    </div>

    <!-- Contents C -->
    <div id="contC" class="contents_inner">
        <!-- ↓↓ 内容が入ります ↓↓ -->
        <h2>Contents C</h2>
        <p>テキストテキストテキストテキストテキストテキストテキスト</p>
    </div>

    <!-- Contents D -->
    <div id="contD" class="contents_inner">
        <!-- ↓↓ 内容が入ります ↓↓ -->
        <h2>Contents D</h2>
        <p>テキストテキストテキストテキストテキストテキストテキスト</p>
    </div>
</div>

前述のソースコード10行目~36行目を<div class=”contents”></div>で囲み、idを指定している<div>タグにはclass=”contents_inner”を設定しました。

そしてCSSにclass=”content”の内容を記述します。

.contents {
	padding-top: 100px;
}

.contents_innner {
    padding-top: 100px;
    margin-top:-100px;
}

これでヘッダーに隠れることなくコンテンツを表示させることができます!

jQueryを使った方法

まずはjQueryファイルを読み込みましょう。<head>内に下記をペースト。 ※</body>直前でもOK

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 

さらに、<head>内に下記を記述。

<script>
jQuery(function(){
    var windowWidth = $(window).width();
    var headerHight = 100; 
    jQuery('a[href^=#]').click(function() {
    var speed = 1000;
    var href= jQuery(this).attr("href");
    var target = jQuery(href == "#" || href == "" ? 'html' : href);
    var position = target.offset().top-headerHight;
    jQuery('body,html').animate({scrollTop:position}, speed, 'swing');
    return false;
   });
});
</script>

この記述で「ジャンプ先のコンテンツの表示エリアについて、ヘッダーの高さ分引いた位置から表示しなさい」という命令をしています。
ついでにスクロールする速さも指定できます。

簡単な解説はこちら。

まとめ

CSSのみで実装する方法は手軽ではありますが、idに別のスタイルを指定している場合などはうまく実装できない時があります。
そんな時は CSS内で完結させようとするより、jQueryを使って実装した方が楽だったりするので、CSSとjQueryどちらも記述の仕方を把握しておくと便利です。

コーディングする内容によってうまく使い分けていきましょう!