JavaScriptのIntersectionObserverで柔軟なパララックス表現

パララックス効果とは?

パララックス(Parallax) とは、スクロール時に背景と前面のコンテンツが異なるスピードで動くことで、奥行きや立体感を演出する視覚効果のことです。
Webデザインでは、背景画像をゆっくり動かすことで「動きのある背景」や「没入感のある演出」に使われます。

従来の「scroll イベント + transform」だけで作る方法に比べて、IntersectionObserver を使うことで、以下のようなメリットがあります

  • 対象が見えたタイミングで動作開始
  • スクロールイベントの無駄な処理を減らせる
  • より軽量で拡張性のある視差表現が可能

また、複数のセクションを交互に配置し、HTMLの data-speed 属性を使って、セクションごとに異なる視差速度を調整する方法を行います。

ここでは、セクション単位の背景パララックスを IntersectionObserver + scrollY + transform: translateY() で実装していきます。

基本構成

See the Pen IntersectionObserverで柔軟なパララックス表現 by Yoshiko Nakamura (@Yoshiko-Nakamura) on CodePen.

HTML

    <!-- パララックス付き -->
    <section class="parallax-container">
        <div class="parallax-bg js-parallax" data-speed="0.3">
            <img src="https://picsum.photos/id/1036/1200/800" alt="">
        </div>
        <div class="content">
            <h2>Parallaxセクション 1</h2>
            <p>テキストがここに入ります…</p>
        </div>
    </section>

    <!-- 通常のセクション -->
    <section class="normal-section">
        <div class="content">
            <h2>通常セクション</h2>
            <p>ここは固定背景のセクションです。視差なし。</p>
            <p>ここは固定背景のセクションです。視差なし。</p>
            <p>ここは固定背景のセクションです。視差なし。</p>
            <p>ここは固定背景のセクションです。視差なし。</p>
            <p>ここは固定背景のセクションです。視差なし。</p>
            <p>ここは固定背景のセクションです。視差なし。</p>
        </div>
    </section>

    <!-- 再びパララックス -->
    <section class="parallax-container">
        <div class="parallax-bg js-parallax" data-speed="0.6">
            <img src="https://picsum.photos/id/1043/1200/800" alt="">
        </div>
        <div class="content">
            <h2>Parallaxセクション 2</h2>
            <p>もう一度、視差効果のあるセクション。</p>
        </div>
    </section>

data-speed とは?

HTMLの属性 data-speed は、「この要素の視差の速さをどれくらいにするか」を指定するためのカスタムデータ属性(data属性)です。

<div class="parallax-bg js-parallax" data-speed="0.3">

この例では、data-speed="0.3" によって「スクロール量 × 0.3」の距離だけ要素が上下に動きます。

値の例意味(動きの速さ)
0.2ゆっくり動く(背景っぽい奥行き効果)
0.6速く動く(前景に近い動き)

data- で始まる属性は HTML5 で追加された仕様で、JavaScript から自由に値を読み取ることができます。JavaScript側では element.dataset.speed という形でアクセスできます。

基本のCSS

        .parallax-container {
            position: relative;
            height: 100vh;
            overflow: hidden;
        }

        .parallax-bg {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 120%;
            /* 少し大きくしておくと自然に動く */
            z-index: 1;
            overflow: hidden;
        }

        .parallax-bg img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        .content {
            position: relative;
            z-index: 2;
            padding: 4rem;
            color: white;
            text-shadow: 0 0 5px #000;
            line-height: 2;
        }

        .normal-section {
            margin: 0;
            background: #6db7f78b;
            padding: 6rem 4rem;
        }

JavaScript

以下のコードは、IntersectionObserverを使って「スクロール位置に応じたパララックス効果」を実現するものです。要素が画面に表示されたら処理を開始し、data-speed に応じて背景画像を上下に動かします。

const targets = document.querySelectorAll('.js-parallax');

        targets.forEach(el => {
            let isScrolling = false;
            const speed = parseFloat(el.dataset.speed);
            const container = el.closest('.parallax-container');

            const updateParallax = () => {
                const scrollY = window.scrollY;
                const offsetTop = container.offsetTop;
                const distance = scrollY - offsetTop;
                el.style.transform = `translateY(${distance * speed}px)`;
            };

            const observer = new IntersectionObserver((entries, obs) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting && !isScrolling) {
                        isScrolling = true;
                        updateParallax(); // 初期表示
                        window.addEventListener('scroll', updateParallax);
                        obs.unobserve(el); // もう監視しない(登録1回でOK)
                    }
                });
            });

            observer.observe(el);
        });
  • document.querySelectorAll('.js-parallax')対象となるすべての視差要素を取得します。
  • data-speed:HTMLで設定した速度を読み取ります(例:data-speed="0.3")。
  • el.datasetel 要素の data- で始まる属性をまとめたオブジェクト.speeddata-speed に対応(ハイフンをキャメルケースに変換)parseFloat() は文字列として取得される値を数値に変換
  • IntersectionObserver:対象がビューポートに入ったタイミングでイベントを登録します。
  • scroll イベントで transform: translateY() を使い、背景を上下に動かします。
  • obs.unobserve():不要になった監視を解除して、無駄な再処理を防ぎます。