LoginSignup
0
3

More than 5 years have passed since last update.

スクロールするとナビゲーション固定(フッターまでスクロールすると消えるタイプ・開閉式のコンテンツ含む)

Posted at

ナビゲーションを固定するtipsはよく見かけますが、
開閉するコンテンツが含まれる場合、documentの高さをどうやって再取得したら良いんだろう、、、
と少しハマってしまったので、メモメモ。

sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>header固定+ドロップダウン</title>
    <link href="sample.css" rel="stylesheet">
</head>

<body>
    <header><h1>header固定+ドロップダウンのサンプル</h1></header>

   <nav>
       <ul>
           <li>リスト1</li>
           <li>リスト2</li>
           <li>リスト3</li>
           <li>リスト4</li>
       </ul>
   </nav>

    <main>
        <section>
            <h2>ココをクリックすると内容が開きます。</h2>
            <p>これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。</p>
        </section>

        <section>
            <h2>ココをクリックすると内容が開きます。</h2>
            <p>これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。</p>
        </section>

        <section>
            <h2>ココをクリックすると内容が開きます。</h2>
            <p>これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。</p>
        </section>

        <section>
            <h2>ココをクリックすると内容が開きます。</h2>
            <p>これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。</p>
        </section>

        <section>
            <h2>ココをクリックすると内容が開きます。</h2>
            <p>これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。これが内容です。</p>
        </section>
    </main>

    <footer></footer>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="sample.js"></script>
</html>
sample.css
@charset "UTF-8" ;

*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    text-align: center;
}

header{
    height: 200px;
    background: #baa7c5;
    color: #fff;
}
header h1{
    line-height: 6;
}

nav{
    background: #2e889c;
    transition: .3s;
}
nav ul{
    display: flex;
    list-style: none;
    justify-content: center;
}
nav ul li{
    padding: 10px 20px;
}

main{ padding-top: 50px;}
main section{
    max-width: 960px;
    margin: 0 auto 50px;
    background: #f0f0f0;
    padding: 20px;
}
main section h2{ margin-bottom: 10px;}
main section h2 + p{
    display: none;
    background: #888;
    color: #eee;
    margin-top: 10px;
    padding: 10px;
}

.is-fixed {
    position: fixed;
    bottom: 0;
    left: 0;
    z-index: 2;
    width: 100%;
}
.is-hide {
    transform: translateY(100%);
}

footer{
    height: 200px;
    background: #2c3e50;
    color: #fff;
}
sample.js
$(function() {

    //開閉
    $("h2").on("click", function() {
        $(this).next("p").slideToggle().toggleClass("open");
        if ($(this).next("p").hasClass("open")) {
            $(this).text("ココをクリックすると内容が閉じます。");
        }
        else {
            $(this).text("ココをクリックすると内容が開きます。");
        }
    });

    //nav固定
    var $win = $(window),
        $main = $('main'),
        $nav = $('nav'),
        navHeight = $nav.outerHeight(),
        footerHeight = $('footer').outerHeight(),
        docmentHeight = $(document).height(),
        navPos = $nav.offset().top,
        fixedClass = 'is-fixed',
        hideClass = 'is-hide';

    /* スクロールした時 */
    $win.on('load scroll', function() {
        var value = $(this).scrollTop(),
            scrollPos = $win.height() + value;

        if ( value > navPos ) {
            if ( docmentHeight - scrollPos <= footerHeight ) {
                $nav.addClass(hideClass);
            } else {
                $nav.removeClass(hideClass);
            }
            $nav.addClass(fixedClass);
        } else {
            $nav.removeClass(fixedClass);
        }
    });

    /* 開閉してdocumentの高さが変わった時 */
    $("h2").on('click', function(){
        $win.on('load scroll', function() {
            var value02 = $(this).scrollTop(),
                docmentHeight02 = $(document).height(),
                scrollPos02 = $win.height() + value02;

            $nav.removeClass('is-hide');
            if ( value02 > navPos ) {
                if ( docmentHeight02 - scrollPos02 <= footerHeight ) {
                    $nav.addClass(hideClass);
                } else {
                    $nav.removeClass(hideClass);
                }
                $nav.addClass(fixedClass);
            } else {
                $nav.removeClass(fixedClass);
            }
        });
    });

});

スクロールした時とクリックした時を一緒に処理しようとしていたために、
ややこしく感じてしまいました。
結果、分けて書けば特に難しいことはなかったです。
(もっとスマートな書き方があれば教えてください。)

参考

ナビゲーションの固定に関しては、こちらの記事の5番目を参考にしました。
大変わかりやすい記事でありがたいです。
jQuery:スクロールしたらヘッダーやナビゲーションを固定・変化させる動きを実装するサンプルコード 5/NxWorld

0
3
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
0
3