LoginSignup
8
4

More than 5 years have passed since last update.

jQuery+CSS3でスクロールしたときに、ナビゲーションヘッダーを固定する方法

Last updated at Posted at 2017-12-07

はじめに

弊社の一部のサービス・ページで使用している、
スクロールしたときに、ナビゲーションヘッダーを固定する方法をご紹介したいと思います:grinning:
(本記事用に若干修正いたしました)

固定する方法は、2パターン

  • タブ切り替えでコンテンツに移動するパターン
  • アンカーリンクでコンテンツに移動するパターン

ページの構成によって、使い分けています。

実装方法

head内にjQueryを読み込ませます。

html5
<script src="https://code.jquery.com/jquery-1.10.1.min.js"></script>

【パターン1】 タブ切り替えでコンテンツに移動するパターン

1.png

javascript

javascript:タブ切り替え
<script>
    $(function() {
        // タブの切替
        $(".tab__block a").click(function() {
            $(".tab__block a").removeClass("select"); // classを削除
            $(this).addClass("select"); // クリックしたナビゲーションにclassを追加
            $("html,body").animate({scrollTop:$("#top").offset().top}); // コンテンツ上部までスクロール
            var num = $(".tab__block a").index(this);
            $(".wrap").removeClass("select"); // classを削除
            $(".wrap").eq(num).addClass("select"); // コンテンツにclassを追加し、表示を切り替える
        });

        // ヘッダーを固定
        var bt = $("#nav").offset().top; // ページ上からの距離を取得
        var ds = 0;

        $(document).scroll(function(){ // スクロール発生時の処理の記述を開始
            ds = $(this).scrollTop(); // スクロールした距離を取得
            if (bt <= ds) {  // スクロール距離がnavの位置を超えると
                $("#nav").addClass("follow"); // classを追加
            } else if (bt > ds) { // スクロールがページ上まで戻ると、
                $("#nav").removeClass("follow"); // classを削除
            }
        });
    });
</script>
  • タブ<a>をクリックすると、class="select"が追加され、コンテンツ上部まで移動します。また違うタブ<a>をクリックすると、別のコンテンツの上部に移動します。
  • スクロールイベントが始まると、スクロールした距離を取得します。ヘッダーの距離まで移動すると、id="nav"class="follow"が追加され、position: fixed; top: 0;が付与され固定されます。スクロールがヘッダーより上に戻ると、id="nav"class="follow"が削除され、固定されなくなります。

Sass

Sass
// ナビの高さ
$navi_height: 68px;

.body {
    position: relative;
    // ナビ
    .tab__block {
        position: absolute;
        top: 0;
        box-sizing: border-box;
        width: 100%;
        height: $navi_height;
    }
    .tab {
        a.select {
            // 選択時の指定
        }
    }
    // コンテンツを囲む
    .wrap {
        display: none;
        padding-top: $navi_height;
        &.select {
            display: block;
        }
    }
}

// スクロールで付加される
.follow {
    position: fixed! important;
    top: 0! important;
    z-index: 10;
    width: 100%;
}
  • $navi_heightにナビゲーションの高さを指定します
  • ※装飾部分は省略しています

HTML

html5:タブ切り替え
<header><!-- メインビジュアルはこの位置 --></header>
<div class="body" id="top">
    <div id="nav" class="tab__block">
        <ul>
            <li class="tab"><a href="javascript: void(0);" class="select">AAA</a></li>
            <li class="tab"><a href="javascript: void(0);">BBB</a></li>
            <li class="tab"><a href="javascript: void(0);">CCC</a></li>
            <li class="tab"><a href="javascript: void(0);">DDD</a></li>
            <li class="tab"><a href="javascript: void(0);">EEE</a></li>
        </ul>
    </div>
    <div class="wrap select">
        <p>AAA</p>
    </div>
    <div class="wrap">
        <p>BBB</p>
    </div>
    <div class="wrap">
        <p>CCC</p>
    </div>
    <div class="wrap">
        <p>DDD</p>
    </div>
    <div class="wrap">
        <p>EEE</p>
    </div>
</div>
  • 初期表示するコンテンツには、class="select"を指定しておきます。
  • ※装飾部分は省略しています

【パターン2】 アンカーリンクでコンテンツに移動するパターン

2.png

javascript

javascript:アンカーリンク
<script>
    $(function() {
        // #で始まるアンカーをクリックした処理
        $('a[href^=#]').click(function() {
            var headerHight = 68; // 固定ヘッダーの高さ
            var speed = 400; // スクロールの速度ミリ秒
            var href= $(this).attr("href"); // アンカーの値取得
            var target = $(href == "#" || href == "" ? 'html' : href); // 移動先を取得
            var position = target.offset().top-headerHight; // 移動先を数値で取得
            $('body,html').animate({scrollTop:position}, speed, 'swing'); // スムーススクロール
            return false;
        });

        // ヘッダーを固定
        var bt = $("#nav").offset().top; // ページ上からの距離を取得
        var ds = 0;

        $(document).scroll(function(){ // スクロール発生時の処理の記述を開始
            ds = $(this).scrollTop(); // スクロールした距離を取得
            if (bt <= ds) {  // スクロール距離がnavの位置を超えると
                $("#nav").addClass("follow"); // classを追加
            } else if (bt > ds) { // スクロールがページ上まで戻ると、
                $("#nav").removeClass("follow"); // classを削除
            }
        });
    });
</script>
  • タブ<a>をクリックすると、アンカーリンク先の値を取得し、コンテンツ上部まで移動します。また違うタブ<a>をクリックすると、別のコンテンツの上部に移動します。
  • スクロールイベントが始まると、スクロールした距離を取得します。ヘッダーの距離まで移動すると、id="nav"class="follow"が追加され、position: fixed; top: 0;が付与され固定されます。スクロールがヘッダーより上に戻ると、id="nav"class="follow"が削除され、固定されなくなります。

Sass

Sass
// ナビの高さ
$navi_height: 68px;

.body {
    position: relative;
    // ナビ
    .tab__block {
        position: absolute;
        top: 0;
        box-sizing: border-box;
        width: 100%;
        height: $navi_height;
    }
    // コンテンツを囲む
    .wrap {
        padding-top: $navi_height;
    }
}

// スクロールで付加される
.follow {
    position: fixed! important;
    top: 0! important;
    z-index: 10;
    width: 100%;
}
  • $navi_heightにナビゲーションの高さを指定します
  • ※装飾部分は省略しています

HTML

html5:アンカーリンク
<header><!-- メインビジュアルはこの位置 --></header>
<div class="body" id="top">
    <div id="nav" class="tab__block">
        <ul>
            <li class="tab"><a href="#AAA">AAA</a></li>
            <li class="tab"><a href="#BBB">BBB</a></li>
            <li class="tab"><a href="#CCC">CCC</a></li>
            <li class="tab"><a href="#DDD">DDD</a></li>
            <li class="tab"><a href="#EEE">EEE</a></li>
        </ul>
    </div>
    <div class="wrap">
        <div id="AAA" class="content">
            <p>AAA</p>
        </div>
        <div id="BBB" class="content">
            <p>BBB</p>
        </div>
        <div id="CCC" class="content">
            <p>CCC</p>
        </div>
        <div id="DDD" class="content">
            <p>DDD</p>
        </div>
        <div id="EEE" class="content">
            <p>EEE</p>
        </div>
    </div>
</div>
  • ※装飾部分は省略しています
8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4