11 スクロールして表示されたタイミングでアニメーションを動かす方法

Webページを閲覧しているときに、スクロールしていてビューポート内に要素が入ったらアニメーションが動き始める、というケースは沢山見かけると思います。そのように動かす方法をここで学んでいきましょう。

目次

CSSだけでスクロール検知してアニメーションさせる

CSSスクロール連動は、Safari 26正式リリース(2025年秋頃)から実用開始か

今までは、ビューエリアに要素が表示されるタイミングの検知は、JavaScriptで行うのが一般的でした。
Chromeにて、CSSスクロール連動機能が2023年7月ごろにリリースされ、Safariでは2025年秋に正式リリースの方向でベータ版が6月にリリースされています。Firefoxでは、設定で有効化できますが、正式リリースの時期は未定です。

2024年6月~2025年6月のシェアは、Chrome 56.12%, Safari 25.54%, Edge 10.67%, Firefox 3.39%となっています。
一般的にFirefoxの利用率は非常に低いので、Safariの正式リリースをもって実用化が開始され始めるでしょう。

Browser Market Share Japan
https://gs.statcounter.com/browser-market-share/all/japan

無名スクロール進行タイムライン – animation-timeline: scroll();

この例では、3つのitem要素に対して、1つ目3つ目には透明度、2つ目には縦位置に対してアニメーションを設定しています。

無名スクロール進行タイムライン – animation-timeline: scroll();
https://developer.mozilla.org/ja/docs/Web/CSS/animation-timeline/scroll

アニメーション範囲
https://developer.mozilla.org/en-US/docs/Web/CSS/animation-range

HTML

<div class="flex-wrap-col3">
    <div class="item fuwari">
        <a data-fancybox="group1" data-src="./image/image-beach.jpg" data-caption="Beach">
            <img src="./image/image-beach.jpg" alt="beach" />
        </a>
        <h3>Beach</h3>
    </div>
    <div class="item downup">
        <a data-fancybox="group1" data-src="./image/image-lake.jpg" data-caption="Lake">
            <img src="./image/image-lake.jpg" alt="lake" />
        </a>
        <h3>Lake</h3>
    </div>
    <div class="item fuwari">
        <a data-fancybox="group1" data-src="./image/image-tram.jpg" data-caption="Tram">
            <img src="./image/image-tram.jpg" alt="tram" />
        </a>
        <h3>Tram</h3>
    </div>
</div>

CSS

/*Scroll Animation*/
/*フワッと表示*/
@keyframes scroll-opacity {
    0% {
        opacity: 0%;
    }

    100% {
        opacity: 100%;
    }
}

.fuwari {
    opacity: 0; /*初期値*/
    animation: scroll-opacity linear both; /*アニメーション設定*/
    animation-timeline: scroll(); /*無名スクロール進行タイムライン*/
    animation-range: entry -10% entry 40%; /*アニメーション範囲:ビューポートに対するアニメーション開始・終了位置*/
}

/*下から上へずれる*/
@keyframes scroll-up {
    0% {
        transform: translateY(20%); /*Y軸(縦方向)下側に20%ずらす*/
    }

    100% {
        transform: translateY(0); /*Y軸(縦方向)要素の元の位置*/
    }
}

.downup {
    transform: translateY(20%);
    animation: scroll-up linear both; /*アニメーション設定*/
    animation-timeline: scroll(); /*無名スクロール進行タイムライン*/
    animation-range: entry -10% entry 30%; /*アニメーション範囲:ビューポートに対するアニメーション開始・終了位置*/
}

今までJavaScriptを使って実装していた動きを、CSSだけでシンプルに実装できました。

JavaScriptで画面内へ入ったときに発火する Intersection Observer API

CSSによるanimation-timelineプロパティはスクロール量に応じてアニメーションの進行度を変化させるものですが、ビューポートに要素が入ったことを検知させ、アニメーションを発動させたい、という場合もあります。

そのような場合は、Intersection Observer APIを使ってJavaScriptによってクラス名を付与することでCSSアニメーションを動かします。

この例では、動かしたい要素のHTMLに「observerTarget」クラスをつけ、CSSアニメーション用のクラス「vibrate」のCSS定義を書き、JavaScriptでは「observerTarget」クラスの要素がビューポート内に入ったら、「inActive」クラスを付与するよう、処理を書いています。

HTML

監視対象の要素に「observerTarget」クラスをつけておきます。
「vibrate」クラスは、CSSでアニメーションの設定をするためのものです。

<a class="btn-gform vibrate observerTarget" data-fancybox="gform" data-src="#modal-gform" href="javascript:;">お問い合わせフォーム</a>

CSS

JavaScriptで、見える範囲に「observerTarget」クラスの要素が入ったら、「inActive」クラスが付与されるので、2つのクラスが付いた時に発動するCSSアニメーションの設定を書いておきます

この例では、animista.netからCSSアニメーションの設定を持ってきたあと、「inActive」クラスを追加しています。

/*AnimistaからのCSS+inActiveクラス*/
.vibrate.inActive {
    animation: vibrate 0.5s linear 3 both;
}

@keyframes vibrate {
    0% {
        -webkit-transform: translate(0);
        transform: translate(0);
    }

    20% {
        -webkit-transform: translate(-2px, 2px);
        transform: translate(-2px, 2px);
    }

    40% {
        -webkit-transform: translate(-2px, -2px);
        transform: translate(-2px, -2px);
    }

    60% {
        -webkit-transform: translate(2px, 2px);
        transform: translate(2px, 2px);
    }

    80% {
        -webkit-transform: translate(2px, -2px);
        transform: translate(2px, -2px);
    }

    100% {
        -webkit-transform: translate(0);
        transform: translate(0);
    }
}

JavaScript

監視対象=observerTargetクラス、交差したらinActiveクラスを付与する処理をJavaScriptで定義しています。
「observerTarget」クラスはHTML内で複数の要素に設定可能です。

const target = document.querySelectorAll('.observerTarget');

const options = {
    root: null, /*null時はビューポート*/
    rootMargin: "10px", /*交差を検知するルート要素からの距離*/
    threshold: 0, /*交差判定 交差量が0になった瞬間=見え始めと見え終わり*/
};

const observer = new IntersectionObserver(inActiveFunc, options); 
target.forEach((tgt) => {
    observer.observe(tgt);
});

//要素が交差したときの指示
function inActiveFunc(entries) {
    entries.forEach((entry) => {
        const target = entry.target;
        if (entry.isIntersecting) {
            target.classList.add('inActive');
        }
    });
}

ID位置への移動時にスムーススクロール – scroll-behavior: smooth;

上のセクションで説明したスクロールアニメーションとは少し異なるのですが、aタグのhrefでジャンプ先を設定している場合で、ID名(#を含んだ名前)をセットした場合で、ページ内の移動時にアニメーションしながらページ内を移動させるための設定方法です。

html要素に対してscroll-behavior: smooth; を設定するだけです。

CSS

html {
    scroll-behavior: smooth;
}
  • URLをコピーしました!

この記事を書いた人

デジタルハリウッド(専門スクール)講師、大学非常勤講師。
Webサイトのデザイン・コーディング・PHPやJavaScriptによるプログラミング、サーバー設定などのスキルを保有し、企業や事業主からの依頼によりサイト制作を行っている。
クライアントの希望によって会社案内やパンフレットのデザイン、動画制作案件も請けている。
SIer企業でのシステムエンジニアを十数年経験後、2011年よりフリーランスへ転向。

目次