フェードインとスライドインの違いについて

WordPressのページで、スクロールしたときに文章や画像をふわっと表示したり、下からスライドさせたりしたいことがあります。

この記事では、JavaScriptの IntersectionObserver を使って、次の3種類のスクロールアニメーションを実装します。

  • フェードイン:透明な状態からふわっと表示
  • スライドイン:少し下の位置から上へ移動
  • フェード+スライド:下から移動しながらふわっと表示

jQueryは使用しません。

フェードインさせたい要素には fadein、スライドインには slidein、両方を組み合わせたい場合は fade-slide を付けて使います。

1 完成イメージ

実際の表示は次のようになります。

下の3つのサンプルは、画面内に入るとそれぞれ異なる動きで表示されます。

1.1 フェードイン

透明な状態から、ふわっと表示されます。

1.2 スライドイン

少し下の位置から上へ移動します。

1.3 フェード+スライド

下から移動しながら、ふわっと表示されます。

一度表示された要素は、その後画面外へ移動しても最初の状態には戻りません。

2 フェードインとスライドインの違い

3種類の違いは、CSSで何を変化させるかです。

1.1 フェードイン

フェードインは opacity を使います。

opacity: 0;

から、

opacity: 1;

へ変化させることで、透明な状態からふわっと表示します。

1.2 スライドイン

スライドインは transform を使います。

transform: translateY(20px);

から、

transform: translateY(0);

へ変化させることで、少し下の位置から本来の位置へ移動します。

1.3 フェード+スライド

フェード+スライドでは、opacitytransform の両方を使います。

下から移動しながら透明度も変化するため、Webサイトでよく見かける「下からふわっと現れる」動きになります。

3 実装方法

今回はJavaScriptを functions.php に直接書かず、子テーマ内の js/scroll-animation.js に分けて管理します。

3.1 3.1 ディレクトリ構造

この記事では、次のような子テーマを例にします。

  • child-theme/
    • archive.php
    • category.php
    • functions.php
    • footer.php
    • header.php
    • style.css
    • js/
      • scroll-animation.js

今回のスクロールアニメーションで編集するのは、主に次の3ファイルです。

  • functions.php
  • style.css
  • js/scroll-animation.js

archive.phpcategory.phpheader.phpfooter.php は、既存の子テーマに含まれているファイルの例です。今回のアニメーションのために編集する必要はありません。

3.2 3.2 functions.phpでJavaScriptを読み込む

まず、子テーマの functions.php から scroll-animation.js を読み込みます。

// ---------------------------------------------
// スクロールアニメーションJSを読み込む
// ---------------------------------------------
function wptips_enqueue_scroll_animation() {

    $script_path = get_stylesheet_directory() . '/js/scroll-animation.js';

    wp_enqueue_script(
        'wptips-scroll-animation',
        get_stylesheet_directory_uri() . '/js/scroll-animation.js',
        array(),
        file_exists( $script_path ) ? filemtime( $script_path ) : null,
        true
    );
}

add_action( 'wp_enqueue_scripts', 'wptips_enqueue_scroll_animation' );

get_stylesheet_directory_uri() を使って、現在使用している子テーマ内の js/scroll-animation.js を読み込んでいます。

最後の true は、JavaScriptをページ下部で読み込む指定です。

また、filemtime() を使ってファイルの更新時刻をバージョンとして付けています。JavaScriptを修正したときに、古いキャッシュが残りにくくなります。

3.3 3.3 scroll-animation.jsを作成する

子テーマの中に js フォルダを作り、その中に scroll-animation.js を作成します。

ファイルの中には次のJavaScriptを記述します。

document.addEventListener( 'DOMContentLoaded', function() {

    const targets = document.querySelectorAll(
        '.fadein, .slidein, .fade-slide'
    );

    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 );
    } );

} );

このJavaScriptでは、

.fadein, .slidein, .fade-slide

の3種類をまとめて監視しています。

対象の要素が画面内に入ると is-show クラスを追加します。

3.4 3.4 style.cssにアニメーションを追加する

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

/* =========================================================
   スクロールアニメーション
========================================================= */


/* フェードイン */
.fadein {
    opacity: 0;
    transition: opacity 0.6s ease;
}

.fadein.is-show {
    opacity: 1;
}


/* 下からスライドイン */
.slidein {
    transform: translateY(20px);
    transition: transform 0.6s ease;
}

.slidein.is-show {
    transform: translateY(0);
}


/* 下からフェード+スライド */
.fade-slide {
    opacity: 0;
    transform: translateY(20px);
    transition:
        opacity 0.6s ease,
        transform 0.6s ease;
}

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


/* 完成サンプル */
.scroll-animation-demo {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 20px;
    margin: 30px 0;
}

.scroll-animation-demo-item {
    padding: 24px;
    background: #f7f9fb;
    border: 1px solid #dce4eb;
    border-radius: 10px;
}

.scroll-animation-demo-item h3 {
    margin-top: 0;
}


/* スマホ */
@media screen and (max-width: 700px) {

    .scroll-animation-demo {
        grid-template-columns: 1fr;
    }

}


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

    .fadein,
    .slidein,
    .fade-slide {
        opacity: 1;
        transform: none;
        transition: none;
    }

}

3.5 3.5 HTMLでアニメーションを指定する

あとは、動かしたい要素にクラスを付けるだけです。

フェードイン

<p class="fadein">
この文章は、ふわっと表示されます。
</p>

スライドイン

<p class="slidein">
この文章は、下から上へスライドします。
</p>

フェード+スライド

<p class="fade-slide">
この文章は、下から移動しながらふわっと表示されます。
</p>

文章だけでなく、見出し、画像、カード、セクション全体などにも使用できます。

4 IntersectionObserverの仕組み

JavaScriptでは、まずアニメーションの対象となる要素を取得しています。

const targets = document.querySelectorAll(
    '.fadein, .slidein, .fade-slide'
);

その後、それぞれの要素を IntersectionObserver で監視します。

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

画面内へ入った要素には、

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

によって is-show を追加します。

5 表示開始のタイミングを調整する

表示開始位置は、次の部分で指定しています。

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

下方向を -10% にしているため、要素が画面の下端に触れた瞬間ではなく、少し画面内へ入ってからアニメーションが始まります。

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

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

のように変更できます。

6 一度だけアニメーションさせる

要素が表示されたあとは、

observer.unobserve( entry.target );

によって、その要素の監視を終了しています。

そのため、一度表示された要素は、スクロールして画面外へ出ても元の状態には戻りません。

再び同じ場所へ戻ったときにもアニメーションを繰り返さないため、自然な表示になります。

7 アニメーションの速度を変える

現在は3種類とも0.6秒で動くようにしています。

transition: opacity 0.6s ease;

または、

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

0.6s を変更すると、アニメーションの速度を調整できます。

たとえば0.4秒なら少し速く、

0.4s

1秒ならゆっくりした動きになります。

1s

8 スライドする距離を変更する

スライドする距離は、

transform: translateY(20px);

で指定しています。

たとえば、

transform: translateY(40px);

にすると、もう少し下の位置から移動します。

文章を読むページでは、動きを大きくしすぎると目立ちすぎるため、20px前後から調整すると自然です。

9 画像やカードにも使える

スクロールアニメーションは文章だけでなく、画像にも使えます。

<div class="fade-slide">

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

</div>

サービス紹介カードなどにも使用できます。

<div class="service-card fadein">
    サービス1
</div>

<div class="service-card fadein">
    サービス2
</div>

<div class="service-card fadein">
    サービス3
</div>

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

端末でアニメーションなどの動きを減らす設定が利用されている場合は、スクロールアニメーションを無効にします。

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

    .fadein,
    .slidein,
    .fade-slide {
        opacity: 1;
        transform: none;
        transition: none;
    }

}

この場合は、フェードやスライドを行わず、コンテンツを通常の状態で表示します。

11 IntersectionObserverが使えない場合

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

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

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

    return;
}

利用できない場合はアニメーションを行わず、対象の要素を通常表示します。

12 動かない場合の確認ポイント

スクロールアニメーションが動かない場合は、次の点を確認してください。

  • js/scroll-animation.js が正しい場所にあるか
  • functions.php でJavaScriptを読み込んでいるか
  • 対象要素に fadeinslideinfade-slide のいずれかが付いているか
  • style.css が正常に読み込まれているか
  • ブラウザの開発者ツールにJavaScriptエラーが出ていないか
  • キャッシュ系プラグインやサーバーキャッシュが残っていないか

13 まとめ

IntersectionObserver を使うと、WordPressでもスクロール位置に合わせたアニメーションを実装できます。

今回のコードでは、

  • fadein:フェードのみ
  • slidein:下からスライド
  • fade-slide:フェード+スライド

の3種類を使い分けられます。

JavaScriptは js/scroll-animation.js として分離しているため、HTMLやPHPの中へ同じJavaScriptを何度も書く必要もありません。

プロフィール、サービス紹介、画像、お客様の声、カード、見出しなど、スクロールしながら順番に見せたいコンテンツに利用できます。

アニメーションは大きく動かしすぎず、ページを読む邪魔にならない程度に使うと自然なWebページになります。