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


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

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

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>

まあ、
こんな感じです。

ヘッダーがスティッキーじゃないですね。
動的にスティッキーになる様に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に入れてみると

うん。良い感じですね!