Intersection Observerで文字だけフェードインを作る方法|スクロールアニメの基本解説

WordPressの記事や固定ページで、スクロールしたときに文字をふわっと表示させたいことがあります。

今回は、JavaScriptの IntersectionObserver を使って、画面内に入った文章を下から自然にフェードインさせる方法を紹介します。

jQueryは使用しません。フェードインさせたい要素に fadein クラスを付けるだけで使えます。

1 完成イメージ

下の文章は、スクロールして画面内に入ると、少し下からふわっと表示されます。

この文章がスクロールに合わせて、下からふわっと表示されます。

一度表示された文章は、その後画面外へ移動しても再び非表示にはなりません。

2 実装の流れ

今回のフェードインは、次の3つで実装します。

  1. フェードインさせたいHTMLに fadein クラスを付ける
  2. functions.php にJavaScriptを追加する
  3. style.css にフェードイン用のCSSを追加する

3 1.HTMLにfadeinクラスを付ける

フェードインさせたい文章に fadein クラスを付けます。

<p class="fadein">
この文章がスクロールすると、ふわっと表示されます。
</p>

見出しにも使えます。

<h2 class="fadein">
サービスについて
</h2>

複数の文章に付けても問題ありません。

<p class="fadein">
1つ目の文章です。
</p>

<p class="fadein">
2つ目の文章です。
</p>

<p class="fadein">
3つ目の文章です。
</p>

JavaScript側で .fadein が付いた要素をまとめて取得するため、文章を増やしてもJavaScriptを書き直す必要はありません。

4 2.functions.phpにJavaScriptを追加する

次のコードを、子テーマの functions.php に追加します。

// ---------------------------------------------
// フェードインJSをフッターで読み込み
// ---------------------------------------------
add_action( 'wp_footer', 'wptips_fadein_script' );

function wptips_fadein_script() {
    ?>

    <script>
    document.addEventListener( 'DOMContentLoaded', function() {

        const targets = document.querySelectorAll( '.fadein' );

        if ( ! targets.length ) {
            return;
        }

        /* IntersectionObserverが使えない場合は通常表示 */
        if ( ! ( 'IntersectionObserver' in window ) ) {

            targets.forEach( function( target ) {
                target.classList.add( 'is-show' );
            } );

            return;
        }

        const options = {
            root: null,
            rootMargin: '0px 0px -10% 0px',
            threshold: 0
        };

        const observer = new IntersectionObserver(
            function( entries, observer ) {

                entries.forEach( function( entry ) {

                    if ( entry.isIntersecting ) {

                        entry.target.classList.add( 'is-show' );

                        /* 一度表示した要素は監視を終了 */
                        observer.unobserve( entry.target );
                    }

                } );

            },
            options
        );

        targets.forEach( function( target ) {
            observer.observe( target );
        } );

    } );
    </script>

    <?php
}

これで、ページ内にある fadein クラス付きの要素を監視できるようになります。

5 3.CSSを追加する

次のCSSを、子テーマの style.css などへ追加します。


/* -------------------------------------------
 * Intersection Observer でフェードインを作る
 * ----------------------------------------- */

/* フェードイン前 */
.fadein {
    opacity: 0;
    transform: translateY(20px);
    transition:
        opacity 0.8s ease,
        transform 0.8s ease;
}


/* フェードイン後 */
.fadein.is-show {
    opacity: 1;
    transform: translateY(0);
}


/* 動きを減らす設定を利用している場合 */
@media (prefers-reduced-motion: reduce) {

    .fadein {
        opacity: 1;
        transform: none;
        transition: none;
    }

}

6 フェードインする仕組み

最初は、次のCSSによって文章を透明にしています。

opacity: 0;

さらに、

transform: translateY(20px);

を指定して、本来の位置より20px下へ移動させています。

この時点では、文章は見えません。

7 画面内に入るとis-showを追加する

JavaScriptでは、IntersectionObserver を使って .fadein が画面内に入ったかどうかを監視しています。

対象の要素が画面内に入ると、

entry.target.classList.add( 'is-show' );

が実行されます。

これによって、HTMLは実質的に次の状態になります。

<p class="fadein is-show">
この文章が表示されます。
</p>

すると、

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

が適用され、透明だった文章が元の位置へ移動しながら表示されます。

8 IntersectionObserverとは?

IntersectionObserver は、指定した要素がブラウザの表示領域に入ったかどうかを監視できるJavaScriptの機能です。

今回のコードでは、ページ内の .fadein を取得し、

const targets = document.querySelectorAll( '.fadein' );

それぞれの要素を監視しています。

targets.forEach( function( target ) {
    observer.observe( target );
} );

9 少し画面内に入ってから表示する

表示するタイミングは、次の部分で調整しています。

rootMargin: '0px 0px -10% 0px'

下方向を -10% にすることで、要素が画面の一番下に触れた瞬間ではなく、少し画面内へ入ってからフェードインします。

もう少し画面内へ入ってから表示したい場合は、

rootMargin: '0px 0px -20% 0px'

のように変更できます。

10 一度だけフェードインさせる

文章が表示されたあとには、

observer.unobserve( entry.target );

を実行しています。

これは、その要素の監視を終了する処理です。

そのため、一度フェードインした文章は、スクロールして画面外へ出ても再び透明には戻りません。

上へ戻ったときにも何度もアニメーションを繰り返さないため、自然な表示になります。

11 フェードインの速度を変更する

フェードインにかかる時間は、次の 0.8s で指定しています。

transition:
    opacity 0.8s ease,
    transform 0.8s ease;

0.8s は0.8秒です。

速くしたい場合は、

transition:
    opacity 0.4s ease,
    transform 0.4s ease;

ゆっくり表示したい場合は、

transition:
    opacity 1.2s ease,
    transform 1.2s ease;

などに変更できます。

12 下から動く距離を変更する

文章が表示される前の位置は、

transform: translateY(20px);

で指定しています。

もう少し大きく動かしたい場合は、

transform: translateY(40px);

のように変更できます。

数字を大きくするほど、下から上へ移動する距離が大きくなります。

文字を読むページでは、20px前後から調整すると動きが目立ちすぎず自然です。

13 文章以外にも使える

今回は文字をフェードインさせる例ですが、fadein クラスは他のHTML要素にも使用できます。

たとえば画像の場合は、

<div class="fadein">

    <img
        src="/wp-content/uploads/sample.jpg"
        alt="サンプル画像"
    >

</div>

のようにします。

文章と画像をまとめてフェードインしたい場合は、セクション全体に付けることもできます。

<section class="fadein">

    <h2>サービス紹介</h2>

    <p>
        サービスについての説明文です。
    </p>

</section>

14 IntersectionObserverが使えない場合

JavaScriptでは、IntersectionObserver が利用できるかどうかも確認しています。

if ( ! ( 'IntersectionObserver' in window ) ) {

    targets.forEach( function( target ) {
        target.classList.add( 'is-show' );
    } );

    return;
}

利用できない環境ではアニメーションを実行せず、文章をそのまま表示します。

この処理を入れておくことで、JavaScriptは実行できるものの IntersectionObserver が利用できない環境では、アニメーションを行わず文章を通常表示できます。

15 動きを減らす設定にも対応する

端末では、アニメーションなどの動きを減らす設定が利用されている場合があります。

今回のCSSでは、

@media (prefers-reduced-motion: reduce) {

    .fadein {
        opacity: 1;
        transform: none;
        transition: none;
    }

}

を追加しています。

動きを減らす設定が有効な場合は、フェードインを行わず、最初から通常表示します。

フェードインはページを見やすくするための演出なので、アニメーションを使わなくても文章を読める状態にしておきます。

16 フェードインしない場合の確認ポイント

コードを追加しても動かない場合は、次の点を確認してください。

  • 対象の要素に fadein クラスが付いているか
  • CSSが正しく読み込まれているか
  • functions.php にJavaScriptのコードを追加しているか
  • ブラウザの開発者ツールにJavaScriptエラーが出ていないか
  • キャッシュ系プラグインやサーバーキャッシュが残っていないか
  • テーマで wp_footer() が実行されているか

17 functions.phpとCSSは別々に記述する

今回の実装では、JavaScriptを出力するコードとCSSを分けて記述します。

  • HTML:フェードインさせたい場所に fadein を付ける
  • functions.php:画面内に入ったことをJavaScriptで判定する
  • style.css:フェードイン前と表示後の見た目を設定する

子テーマを使用している場合は、PHPとCSSのどちらも子テーマ側へ追加しておくと管理しやすくなります。

18 まとめ

IntersectionObserver を使うと、WordPressでもスクロールに合わせたシンプルなフェードインを実装できます。

  • jQueryは不要
  • fadein クラスを付けるだけで使える
  • 画面内へ入ったタイミングで表示できる
  • 一度表示した要素は監視を終了する
  • 表示速度や移動距離をCSSで変更できる
  • 動きを減らす設定にも対応できる
  • IntersectionObserver が利用できない場合は通常表示に切り替えられる

文章を大きく動かしすぎず、少し下から自然に表示する程度にすると、本文を読む邪魔になりにくいフェードインになります。

プロフィール、サービス紹介、説明文、見出しなど、スクロールしながら順番に見せたい内容に活用できます。