JavaScriptのスクロールイベント(scrollY を使った動き)

スクロールする度に、固定されているボタンがふわっと表示されたり、最初は出ていて、スクロールすると消えるヘッダーがある位置に来たら上部に固定するなどはJavaScript scroolYというプロパティを使います。たとえば「上へ戻る」ボタンがスクロール後に表示されたり、スクロール方向によってヘッダーが隠れたりするような動きは、window.scrollY を使ってページのスクロール位置を取得することで実現できます。

1.「上へ戻る」ボタンを表示/非表示

画面右下に固定した「上へ戻る」ためのボタン(アイコン)が、最初から表示するのではなく、画面を 600px 以上スクロールすると、右下に固定された「上へ戻る」ボタンがふわっと表示され、クリックすることでページの先頭へ戻ることができます。

HTML

        <div id="backToTop">
            <a href="#top">
                ▲
            </a>
        </div>

CSS

#backToTop a {
    display: block;
    position: fixed;
    right: 10px;
    bottom: 100px;
    background-color: var(--main-color);
    padding: .75rem 1rem;
    color: var(--white);
    text-decoration: none;
    border-radius: 5px;
    z-index: 200;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.4s ease, visibility 0.4s ease;
}
#backToTop.show a {
    opacity: 1;
    visibility: visible;
}

JavaScript

const backToTop = document.getElementById('backToTop');

window.addEventListener('scroll', () => {
  const scrollY = window.scrollY; // 現在のスクロール量を取得

  if (scrollY > 600) {
    backToTop.classList.add('show');
  } else {
    backToTop.classList.remove('show');
  }
});

window.scrollYとは?

window.scrollY は、ページが どれだけ縦にスクロールされたか(px単位) を取得するプロパティです。

たとえば、scrollY > 600 と書けば、「600px以上スクロールされたかどうか」を判定できます。

毎回 window.scrollY と書くのは少し長いので、下記のように const scrollY = window.scrollY; のように変数に入れておくと、コードが読みやすくなります。

2.スクロール方向でヘッダーを隠す/戻す

ページの上部に表示されているヘッダーは、最初は表示されていますが、ユーザーが下にスクロールすると非表示になり、再び上にスクロールし始めると表示されるようになります。

このような動きは window.scrollY を使い、「今のスクロール位置」と「ひとつ前のスクロール位置」を比較することでスクロールの方向を判定して実現します。

HTML

    <header class="header">
        <h1>サイトのタイトル</h1>
        <nav class="header-list">
            <ul>
                <li><a href="#">About</a></li>
                <li><a href="#">Service</a></li>
                <li><a href="#">Contuct</a></li>
            </ul>
        </nav>
    </header>

    <main style="padding: 2rem;">
        <p style="line-height: 2;">下にスクロールします。</p>
        <p style="line-height: 2;">下にスクロールします。</p>
        <p style="line-height: 2;">下にスクロールします。</p>
        <p style="line-height: 2;">下にスクロールします。</p>
        <p style="line-height: 2;">下にスクロールします。</p>
        <p style="line-height: 2;">下にスクロールします。</p>
        <p style="line-height: 2;">下にスクロールします。</p>
        <p style="line-height: 2;">下にスクロールします。</p>
        <p style="line-height: 2;">下にスクロールします。</p>
        <p style="line-height: 2;">下にスクロールします。</p>
        <p style="line-height: 2;">下にスクロールします。</p>
        <div style="height: 800px;"></div>
    </main>

CSS

        body {
            margin: 0;
            overflow-x: hidden;
        }

        .header {
            position: fixed;
            top: 0;
            width: 100%;
            background: #9e9e9ed6;
            padding: 1rem 2rem;
            box-sizing: border-box;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
            transition: transform 0.3s ease;
            z-index: 500;
            display: flex;
            align-items: center;
            justify-content: space-between;
        }

        /* 非表示時:上に押し上げて隠す */
        .header.hide {
            transform: translateY(-100%);
            transition: transform 0.3s ease;
        }

        .header-list ul {
            list-style: none;
            display: flex;
            gap: 30px
        }

        .header-list ul a {
            color: #000;
            text-decoration: none;
        }

JavaScript

        const header = document.querySelector('.header');
        const main = document.querySelector('main');
        let lastScrollY = window.scrollY;

        // ヘッダーの高さを main に反映(初期設定)
        window.addEventListener('DOMContentLoaded', () => {
            const headerHeight = header.offsetHeight;
            main.style.paddingTop = `${headerHeight}px`;
        });

        window.addEventListener('scroll', () => {
            const currentScrollY = window.scrollY;

            if (currentScrollY > lastScrollY && currentScrollY > 300) {
                header.classList.add('hide');
            } else {
                header.classList.remove('hide');
            }

            lastScrollY = currentScrollY;
        });

.header 要素と <main> 要素を取得。

lastScrollY は「ひとつ前のスクロール位置」を記録しておくための変数です(初期値は現在のスクロール位置)。

main の padding-top をヘッダーの高さにする

window.addEventListener('DOMContentLoaded', () => {
  const headerHeight = header.offsetHeight;
  main.style.paddingTop = `${headerHeight}px`;
});
  • ページのHTMLが読み込まれたら(画像などの読み込み前でもOK)実行されます。
  • header.offsetHeight は、ヘッダーの高さ(ピクセル)を取得。
  • main.style.paddingTop = ... によって、<main> にヘッダーの高さ分の余白を上に追加し、内容が隠れないように調整します。

スクロールイベントでヘッダーを出し入れ

window.addEventListener('scroll', () => {
  const currentScrollY = window.scrollY;
  • スクロールのたびに現在のスクロール位置(縦方向)を取得

下にスクロールしたか?を判定

  if (currentScrollY > lastScrollY && currentScrollY > 300) {
    header.classList.add('hide');
  } else {
    header.classList.remove('hide');
  }
  • currentScrollY > lastScrollY → 前回より下にスクロールした場合
  • currentScrollY > 300 → ページ上部(300px未満)ではヘッダーを常に表示したいので、その範囲は対象外
  • 両方満たすと、.hide クラスを付けてヘッダーを非表示にします。
  • 逆に、上にスクロールした場合や、300pxより上の位置なら、.hide を外して再表示します。

スクロール位置を更新

  lastScrollY = currentScrollY;
});

  • 最後に、今回のスクロール位置を記録して、次回の判定に使います。

3.スクロールで要素をフェードイン/下から上 左から右 右から左

画面を下にスクロールしていくと、各セクションや画像がふわっと表示される演出getBoundingClientRect() を使って、要素が画面内に入ってきたタイミングを検出します。

HTML

 <section class="fadein">下から</section>

    <hr>
    <section class="fadein-left">左から</section>
    <section class="fadein-left">左から</section>
    <hr>
    <section class="fadein-right">右から</section>
    <section class="fadein-right">右から</section>
    <hr>
    <section class="fadein-left">左から</section>
    <section class="fadein-right">右から</section>

CSS

        .fadein,
        .fadein-left,
        .fadein-right {
            opacity: 0;
            transition: all 1s ease;
        }

        /* 下から上 */
        .fadein {
            transform: translateY(100px);
        }

        .fadein.show {
            opacity: 1;
            transform: translateY(0);
        }

        /* 左から右 */
        .fadein-left {
            transform: translateX(-200px);
        }

        .fadein-left.show {
            opacity: 1;
            transform: translateX(0);
        }

        /* 右から左 */
        .fadein-right {
            transform: translateX(200px);
        }

        .fadein-right.show {
            opacity: 1;
            transform: translateX(0);
        }


        section {
            border: 1px solid #999;
            max-width: 500px;
            height: 200px;
            background-color: #eee;
            display: flex;
            justify-content: center;
            align-items: center;
            color: #000;
            margin: 30px auto;
        }

JavaScript

  • .fadein, .fadein-left, .fadein-right というクラスがついた要素をすべて対象にして、
  • 画面内に入ってきたタイミングで .show クラスを追加
  • その結果、CSSで指定されたアニメーション(フェードイン・スライドイン)が実行される
        const items = document.querySelectorAll('.fadein, .fadein-left, .fadein-right');

        const checkFade = () => {
            for (const item of items) {
                const rect = item.getBoundingClientRect();
                if (rect.top < window.innerHeight * 0.8) {
                    item.classList.add('show');
                }
            }
        };


        window.addEventListener('scroll', checkFade);
        window.addEventListener('DOMContentLoaded', checkFade);

const items = document.querySelectorAll('.fadein, .fadein-left, .fadein-right');
  • .fadein 系の3種類すべてをまとめて取得
  • itemsNodeList(配列のようなリスト)になります
  • これがループ処理の対象になります
const checkFade = () => {

  • アロー関数の定義です
  • checkFade はスクロールごとに実行される関数で、「表示チェック」を行います
    for (const item of items) {
  • for...of 文を使って、リスト内の各要素に順番にアクセスします
  • 1つずつ item という変数に取り出して処理します
        const rect = item.getBoundingClientRect();


  • getBoundingClientRect()は、要素の「画面上での位置とサイズ」を取得するメソッド
  • rect.top:その要素の上端が、画面の上から何pxの位置にあるかを表します
        if (rect.top < window.innerHeight * 0.8) {
  • 要素の上端が、ウィンドウの高さ × 0.8 より上に来たら(つまり画面の8割より上に来たら)…
  • 表示開始の条件を満たしたと判断します
            item.classList.add('show');

  • 条件を満たしたら .show クラスを追加
  • CSSで .fadein.show などにアニメーション指定されているので、ここで動きが実行される
window.addEventListener('scroll', checkFade);


  • スクロールするたびに checkFade 関数が実行されます
  • 表示される位置に来た要素をチェックします
window.addEventListener('DOMContentLoaded', checkFade);



  • ページが読み込まれた時点(HTML構造ができた時)でも、checkFade を実行
  • 初期状態からすでに画面内にある要素にも .show をつけるためです