スクロールに合わせて要素をフワッと出現させる。
自然で滑らかなアニメーション実装術

UI/UXCSS実装

ページを開いた瞬間にすべての情報が一度に表示されるサイトと、スクロールするたびにコンテンツがふわっと現れるサイト。どちらが「読みたい」と感じるでしょうか?
スクロール連動のアニメーションは、ユーザーの視線を誘導し、コンテンツに「ストーリー性」を生み出す強力なテクニックです。本記事では Intersection Observer API とCSSを組み合わせた4つのパターンを、コピペ可能なコードで解説します。

なぜスクロールアニメーションが効果的なのか

人間の目は「動くもの」に自然と引きつけられます。スクロールに合わせてコンテンツが現れると、ユーザーは無意識のうちにそのコンテンツに注目します。これは特に、サービス紹介や実績紹介など「順序立てて読んでほしい」コンテンツに効果的です。

ただし、やりすぎは逆効果。スクロールのたびに派手なアニメーションが走ると、肝心のコンテンツが頭に入ってきません。「気づかないくらいが、ちょうどいい」が鉄則です。

共通の仕組み:Intersection Observer API

かつてはスクロール位置を scroll イベントで毎フレーム監視するしかありませんでしたが、現在は Intersection Observer API が主流です。要素がビューポートに入った瞬間だけコールバックが走るため、パフォーマンスに優れています。

以下のJavaScriptを1つ書いておけば、4つすべてのパターンに対応できます。

JavaScript
// すべてのスクロールアニメーション対象を監視
const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            entry.target.classList.add('is-visible');
        }
    });
}, {
    threshold: 0.15,  // 15%見えた時点で発火
    rootMargin: '0px 0px -50px 0px'
});

document.querySelectorAll('.fade-in, .slide-left, .slide-right, .scale-in, .stagger-item')
    .forEach(el => observer.observe(el));
💡 ポイント:threshold: 0.15 は「要素の15%がビューポートに入ったら」を意味します。値を大きくすると、より深くスクロールしないと発火しません。0.1〜0.2 がバランスの良い値です。

パターン1:フェードイン + 上方スライド

最も定番で汎用性の高いパターンです。要素が下から30px浮き上がりながらフェードインします。セクションタイトルやテキストブロックに最適です。

フワッと下から出現 ✨
HTML
<div class="box fade-in">フワッと下から出現 ✨</div>
CSS
/* ===== ベースのレイアウト(デザインに合わせて調整してください) ===== */
.box {
    /* 本体のスタイル */
}

/* ===== 動作のアニメーション ===== */
.fade-in {
    opacity: 0;
    transform: translateY(30px);
    transition: opacity 0.8s ease,
                transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}

.fade-in.is-visible {
    opacity: 1;
    transform: translateY(0);
}

パターン2:左右からのスライドイン

2カラムレイアウトで、左の要素は左から、右の要素は右からスライドインさせると、コンテンツに「出会い」の印象が生まれます。ビフォーアフターや比較表示にぴったりです。

← 左からスライドイン
右からスライドイン →
HTML
<div class="box slide-left">← 左からスライドイン</div>
<div class="box slide-right">右からスライドイン →</div>
CSS
/* ===== ベースのレイアウト(デザインに合わせて調整してください) ===== */
.box {
    /* 本体のスタイル */
}

/* ===== 動作のアニメーション ===== */
.slide-left {
    opacity: 0;
    transform: translateX(-40px);
    transition: opacity 0.7s, transform 0.7s cubic-bezier(0.4, 0, 0.2, 1);
}
.slide-left.is-visible {
    opacity: 1;
    transform: translateX(0);
}

.slide-right {
    opacity: 0;
    transform: translateX(40px);
    transition: opacity 0.7s, transform 0.7s cubic-bezier(0.4, 0, 0.2, 1);
}
.slide-right.is-visible {
    opacity: 1;
    transform: translateX(0);
}

パターン3:スケールイン(拡大して登場)

要素が少し小さい状態から原寸大に拡大しながら出現します。ヒーロー画像やロゴの登場に使うと、存在感のある印象になります。

ポンッと拡大して登場 🎯
HTML
<div class="box scale-in">ポンッと拡大して登場 🎯</div>
CSS
/* ===== ベースのレイアウト(デザインに合わせて調整してください) ===== */
.box {
    /* 本体のスタイル */
}

/* ===== 動作のアニメーション ===== */
.scale-in {
    opacity: 0;
    transform: scale(0.9);
    transition: opacity 0.6s,
                transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.scale-in.is-visible {
    opacity: 1;
    transform: scale(1);
}
💡 ポイント:cubic-bezier(0.34, 1.56, 0.64, 1) は「少しだけ行き過ぎてから戻る」イージング。バウンス感のある気持ちいい動きになります。

パターン4:スタガー(時間差)アニメーション

複数の要素がパラパラと順番にフェードインする「スタガーアニメーション」。カードの一覧やチームメンバーの紹介に使うと、リズム感のある美しい画面が生まれます。

01
02
03
04
05
06
HTML
<div class="stagger-grid">
    <div class="stagger-item" style="transition-delay: 0s;">01</div>
    <div class="stagger-item" style="transition-delay: 0.1s;">02</div>
    <div class="stagger-item" style="transition-delay: 0.2s;">03</div>
    <div class="stagger-item" style="transition-delay: 0.3s;">04</div>
    <div class="stagger-item" style="transition-delay: 0.4s;">05</div>
    <div class="stagger-item" style="transition-delay: 0.5s;">06</div>
</div>
CSS
/* ===== ベースのレイアウト(デザインに合わせて調整してください) ===== */
.stagger-grid {
    /* 本体のスタイル */
}

/* ===== 動作のアニメーション ===== */
.stagger-item {
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 0.5s, transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.stagger-item.is-visible {
    opacity: 1;
    transform: translateY(0);
}
/* 各要素にHTMLで transition-delay を設定 */
.stagger-item:nth-child(1) { transition-delay: 0s; }
.stagger-item:nth-child(2) { transition-delay: 0.1s; }
.stagger-item:nth-child(3) { transition-delay: 0.2s; }
/* ...以降も 0.1s ずつ加算 */

まとめ:スクロールに「語り」を添える

スクロールアニメーションの目的は「派手さ」ではなく、ユーザーの視線を自然に導き、コンテンツに物語性を持たせることです。今回紹介した4パターンをまとめます。

共通する鉄則は「移動量は20〜40px以内に抑える」「所要時間は0.5〜0.8秒」の2点。大きく動かしすぎると酔いの原因になり、遅すぎるとテンポが悪くなります。

💡 アクセシビリティ配慮:prefers-reduced-motion: reduce メディアクエリで、ユーザーの設定に応じてアニメーションを無効化しましょう。
@media (prefers-reduced-motion: reduce) { .fade-in, .slide-left, .slide-right, .scale-in { transition: none; opacity: 1; transform: none; } }
川村 小百合

この記事の執筆者

川村 小百合 株式会社ツタワル 代表取締役

日本有数のテーマパークのWebデザインや、株式会社ポケモンのグラフィックデザイナーを経て、これまで200サイト以上のWEB制作や数多くのグラフィックデザインを経験。お客様の売上に直結する「デザインに強いWeb制作」をはじめ、販促POP制作から商品開発に至るまで、企画から実制作までを一気通貫でサポートしています。「社員クリエイターを1人雇うコストで、腕のあるプロへきめ細かく月極依頼ができる」体制を提供し、ビジネス成長の心強いパートナーとして企業の販促活動に伴走します。

この人に相談する

Contact

伝わるまで、何度でも。

あなたのブランドの「言葉」と「形」を、一緒に見つけませんか?
些細なご相談でも、まずはお気軽にお話ししましょう。