LoginSignup
0
0

More than 3 years have passed since last update.

スクロールに追随する複数のヘッダーの作り方

Last updated at Posted at 2020-05-11

画面のスクロールに応じて変化するスティッキーなヘッダーの作り方

✴︎要はこれを自作で作る方法

HTML,CSS

サンプルとして、以下の様なヘッダーとブロックを持つdiv要素の群があるとします。

sample.html
<!DOCTYPE HTML>
<html>
    <style>
        body {
            margin: unset;
        }
        div.block{
            height: 2600px;
            width: 100%;
        }
        div.block.one{
            background-color: #C1A1FF;
        }
        div.block.two{
            background-color: #9892E8;
        }
        div.block.three{
            background-color: #AEBEFF;
        }
        div.block.four{
            background-color: #92BAE8;
        }
        div.header{
            font-size: 1.5em;
            text-align: center;
        }
        div.header.one{
            background-color: #A269FF;
        }
        div.header.two{
            background-color: #6D5FE8;
        }
        div.header.three{
            background-color: #768DFF;
        }
        div.header.four{
            background-color: #5797EB;
        }

    </style>
    <body >
        <div class='block one'>
            <div class="header one">
                This is Header Number one.
            </div>
        </div>
        <div class='block two'>
            <div class="header two">
                This is Header Number two.
            </div>
        </div>
        <div class='block three'>
            <div class="header three">
                This is Header Number three.
            </div>
        </div>
        <div class='block four'>
            <div class="header four">
                This is Header Number four.
            </div>
        </div>
    </body>
</html>

まあ、
こんな感じです。
画面収録-2020-05-11-23.26.36.gif

ヘッダーがスティッキーじゃないですね。
動的にスティッキーになる様にJSを足しましょう。

JS

sample.js
    let activateStickyHeader = function() {
        let blocks = document.getElementsByClassName('block');

        let targetHeight = [];
        for (let i = 0; i < blocks.length; i++) {
            targetHeight.push(blocks[i].getBoundingClientRect().top + window.pageYOffset);
        }
        let headers = document.getElementsByClassName('header')

        document.addEventListener('scroll', function(){
            let y = window.pageYOffset ;
            for (let key in targetHeight) {

                if(  y >= targetHeight[key]){
                    headers[key].style.position = 'sticky';
                    headers[key].style.top = '0';
                } else {
                    headers[key].style.position = '';
                    headers[key].style.top = '';
                }
            }
        })
    };

    document.addEventListener("DOMContentLoaded", function(){
        activateStickyHeader()
    }, false);
JS処理で何をやっているか。

document.getElementsByClassName('block')
でそれぞれのブロックの要素を取得し、
blocks[i].getBoundingClientRect().top + window.pageYOffset
これで各ブロック要素の画面上の位置(スクロール量を未考慮)+ページトップを0とした時の画面を開いた時のスクロール量
= ページ内の位置 となります。

これらを配列に入れ、ウインドウのスクロール位置が各ブロックのページ内の位置に到達した際に、
対応するヘッダーのスタイルを書き換えてスティッキーなヘッダーにしています。

sample.jsをsample.htmlに入れてみると
画面収録-2020-05-11-23.27.59.gif

うん。良い感じですね!

0
0
2

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
0