戻る
ITトレンド

【コピペOK】ライブラリ不要!スクロールで動くCSSアニメーション集20選

2026/7/30
【コピペOK】ライブラリ不要!スクロールで動くCSSアニメーション集20選

AOSやGSAPなどのライブラリを入れなくても、スクロールで要素がふわっと出てくるアニメーションは作れます。本記事では、CSSと十数行のJavaScriptだけで動くスクロールリビールを、クラス名を付けるだけで使える形にまとめて20パターン紹介します。

使い方はシンプルです。

  1. 共通のCSSとJSを1回だけ読み込む
  2. 動かしたい要素に reveal とバリエーション用のクラスを付ける

以前公開したボタンデザイン集24選と同じく、すべてコピー&ペーストで使えます。

記事内のプレビューは表示後の見た目です(枠とカードで示します)。実際のスクロール動作はセットアップ後に確認してください。


はじめに:仕組みの全体像

やることは2つだけです。

  • CSS: 初期状態(見えない)と、表示後の状態(見える)を定義する
  • JS: IntersectionObserver で画面に入ったら is-inview クラスを付ける

クラス名の設計は次のとおりです。

クラス役割
reveal必須。リビール対象の目印
reveal--up など動きのバリエーション
reveal--delay-1 など遅延
reveal--slow / reveal--fast速度
reveal--repeat画面外に出たら再度隠す
is-inviewJSが自動付与。手動で書かない

transformopacity(必要なら filter / clip-path)だけを動かすので、体感も軽く、ライブラリ不要です。


0. セットアップ(これだけコピペ)

サイトに1回入れれば、あとはHTMLにクラスを足すだけで動きます。

HTML(読み込み例)

<link rel="stylesheet" href="/css/reveal.css" />
<!-- 本文のどこかに -->
<section class="reveal reveal--up">
  <h2>見出しが下からふわっと出る</h2>
</section>

<script src="/js/reveal.js" defer></script>

CSS(reveal.css 全文)

/* ===== Scroll Reveal - base ===== */
@media (prefers-reduced-motion: no-preference) {
  .reveal {
    opacity: 0;
    transition-property: opacity, transform, filter, clip-path;
    transition-duration: 0.7s;
    transition-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
    transition-delay: 0s;
    will-change: opacity, transform;
  }

  .reveal.is-inview {
    opacity: 1;
    transform: none;
    filter: none;
    clip-path: none;
  }

  /* directions */
  .reveal--fade { transform: none; }
  .reveal--up { transform: translateY(32px); }
  .reveal--down { transform: translateY(-32px); }
  .reveal--left { transform: translateX(-40px); }
  .reveal--right { transform: translateX(40px); }

  /* scale / blur / rotate */
  .reveal--scale { transform: scale(0.88); }
  .reveal--zoomout { transform: scale(1.12); }
  .reveal--blur { filter: blur(12px); transform: translateY(12px); }
  .reveal--rotate { transform: rotate(-8deg) translateY(24px); }
  .reveal--flip {
    transform: perspective(800px) rotateX(72deg);
    transform-origin: center bottom;
  }

  /* clip / mask style */
  .reveal--clip-up {
    opacity: 1;
    clip-path: inset(100% 0 0 0);
  }
  .reveal--clip-left {
    opacity: 1;
    clip-path: inset(0 100% 0 0);
  }
  .reveal--circle {
    opacity: 1;
    clip-path: circle(0% at 50% 50%);
  }
  .reveal--clip-up.is-inview,
  .reveal--clip-left.is-inview,
  .reveal--circle.is-inview {
    clip-path: inset(0);
  }
  .reveal--circle.is-inview {
    clip-path: circle(75% at 50% 50%);
  }

  /* image helpers */
  .reveal--wipe {
    opacity: 1;
    clip-path: inset(0 100% 0 0);
  }
  .reveal--wipe.is-inview {
    clip-path: inset(0);
  }
  .reveal--kenburns > img {
    transform: scale(1.15);
    transition: transform 1.2s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .reveal--kenburns.is-inview > img {
    transform: scale(1);
  }

  /* text underline draw */
  .reveal--underline {
    opacity: 1;
    display: inline;
    background-image: linear-gradient(currentColor, currentColor);
    background-repeat: no-repeat;
    background-position: left bottom;
    background-size: 0% 2px;
    transition: background-size 0.8s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .reveal--underline.is-inview {
    background-size: 100% 2px;
  }

  /* stagger: children animate in sequence */
  .reveal--stagger > * {
    opacity: 0;
    transform: translateY(20px);
    transition:
      opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1),
      transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .reveal--stagger.is-inview > *:nth-child(1) { transition-delay: 0.05s; }
  .reveal--stagger.is-inview > *:nth-child(2) { transition-delay: 0.12s; }
  .reveal--stagger.is-inview > *:nth-child(3) { transition-delay: 0.19s; }
  .reveal--stagger.is-inview > *:nth-child(4) { transition-delay: 0.26s; }
  .reveal--stagger.is-inview > *:nth-child(5) { transition-delay: 0.33s; }
  .reveal--stagger.is-inview > *:nth-child(6) { transition-delay: 0.40s; }
  .reveal--stagger.is-inview > * {
    opacity: 1;
    transform: none;
  }

  /* line-by-line text */
  .reveal--lines > * {
    opacity: 0;
    transform: translateY(1em);
    transition:
      opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1),
      transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .reveal--lines.is-inview > *:nth-child(1) { transition-delay: 0.05s; }
  .reveal--lines.is-inview > *:nth-child(2) { transition-delay: 0.15s; }
  .reveal--lines.is-inview > *:nth-child(3) { transition-delay: 0.25s; }
  .reveal--lines.is-inview > *:nth-child(4) { transition-delay: 0.35s; }
  .reveal--lines.is-inview > * {
    opacity: 1;
    transform: none;
  }

  /* delays */
  .reveal--delay-1 { transition-delay: 0.1s; }
  .reveal--delay-2 { transition-delay: 0.2s; }
  .reveal--delay-3 { transition-delay: 0.35s; }
  .reveal--delay-4 { transition-delay: 0.5s; }

  /* speed */
  .reveal--fast { transition-duration: 0.4s; }
  .reveal--slow { transition-duration: 1.1s; }
}

/* reduced motion: always show content */
@media (prefers-reduced-motion: reduce) {
  .reveal,
  .reveal--stagger > *,
  .reveal--lines > *,
  .reveal--kenburns > img {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    clip-path: none !important;
    transition: none !important;
  }
}

JavaScript(reveal.js 全文)

(() => {
  const targets = document.querySelectorAll(".reveal");
  if (!targets.length) return;

  // 動きを抑えたいユーザーは最初から表示
  const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  if (reduce) {
    targets.forEach((el) => el.classList.add("is-inview"));
    return;
  }

  const io = new IntersectionObserver(
    (entries) => {
      for (const entry of entries) {
        const el = entry.target;
        const repeat = el.classList.contains("reveal--repeat");

        if (entry.isIntersecting) {
          el.classList.add("is-inview");
          if (!repeat) io.unobserve(el);
        } else if (repeat) {
          el.classList.remove("is-inview");
        }
      }
    },
    {
      threshold: 0.15,
      // 画面下端より少し手前で発火(早すぎ/遅すぎを緩和)
      rootMargin: "0px 0px -8% 0px",
    }
  );

  targets.forEach((el) => io.observe(el));
})();

これ以降の各パターンは、追加で書くCSSはほぼ不要です。HTMLのクラスを変えるだけです。


1. 基本リビール(5パターン)

セクション見出しやカードの登場に一番よく使う定番です。

1-1. フェードイン

使用シーン: テキストブロック、軽い登場演出

Fade In

HTML:

<div class="reveal reveal--fade">
  コンテンツ
</div>

1-2. 下からスライドアップ

使用シーン: 見出し、CTA、カード一覧の定番

Slide Up

HTML:

<section class="reveal reveal--up">
  <h2>セクション見出し</h2>
</section>

1-3. 上からスライドダウン

使用シーン: 通知バー、上部からの登場演出

Slide Down

HTML:

<div class="reveal reveal--down">上から降りてくる</div>

1-4. 左からスライドイン

使用シーン: 2カラム左カラム、タイムライン

From Left

HTML:

<article class="reveal reveal--left">左から登場</article>

1-5. 右からスライドイン

使用シーン: 2カラム右カラム、交互レイアウト

From Right

HTML:

<article class="reveal reveal--right">右から登場</article>

左右交互にする例:

<div class="feature reveal reveal--left">特徴A</div>
<div class="feature reveal reveal--right">特徴B</div>
<div class="feature reveal reveal--left">特徴C</div>

2. スケール・ブラー・回転(5パターン)

少し個性を出したいときに。やりすぎると重いので、ページ内では1〜2種類に絞るのがおすすめです。

2-1. スケールイン

使用シーン: カード、モーダル風の注目要素

Scale In

HTML:

<div class="reveal reveal--scale">拡大しながら出現</div>

2-2. ズームアウト(奥から手前)

使用シーン: ヒーロー直下のキャッチ、写真ギャラリー

Zoom Out

HTML:

<div class="reveal reveal--zoomout">奥から寄ってくる</div>

2-3. ブラー解除

使用シーン: 写真、引用、フォーカスを当てたい文言

Blur to Clear

HTML:

<blockquote class="reveal reveal--blur">
  ぼやけからシャープに
</blockquote>

2-4. 回転しながら登場

使用シーン: アイコン、バッジ、遊びのあるLP

Rotate In

HTML:

<div class="reveal reveal--rotate">少し傾いて登場</div>

2-5. フリップ(X軸)

使用シーン: カードめくり感、実績数字の強調

Flip In

HTML:

<div class="reveal reveal--flip">
  <strong>120+</strong> projects
</div>

3. クリップ/マスク系(3パターン)

clip-path を使うと、「覆いが取れる」系の演出になります。写真や大きな見出し向きです。

3-1. 下からクリップリビール

使用シーン: 大きな見出し、フル幅ビジュアル

Clip Up

HTML:

<h2 class="reveal reveal--clip-up">切り取られるように表示</h2>

3-2. 左からクリップリビール

使用シーン: 横長バナー、サービス紹介

Clip Left

HTML:

<div class="reveal reveal--clip-left">横方向に開く</div>

3-3. 円形リビール

使用シーン: 円形画像、アバター、ロゴ

HTML:

<img
  class="reveal reveal--circle"
  src="/images/avatar.jpg"
  alt="メンバー写真"
  width="160"
  height="160"
  style="border-radius: 999px; display: block;"
/>

4. スタッガー(順番に出す)

4-1. 子要素を順番にリビール

使用シーン: カードグリッド、特徴リスト、料金プラン

A
B
C

HTML:

<ul class="reveal reveal--stagger" style="display:grid; gap:12px; list-style:none; padding:0;">
  <li>カード1</li>
  <li>カード2</li>
  <li>カード3</li>
  <li>カード4</li>
</ul>

親に reveal reveal--stagger を付け、子は普通の要素でOKです。7個以上並べる場合は、CSSの nth-child 遅延を増やしてください。

.reveal--stagger.is-inview > *:nth-child(7) { transition-delay: 0.47s; }
.reveal--stagger.is-inview > *:nth-child(8) { transition-delay: 0.54s; }

5. テキスト系(2パターン)

5-1. 行ごとにリビール

使用シーン: キャッチコピー、リード文

一行目のメッセージ
二行目のメッセージ

HTML:

<h1 class="reveal reveal--lines">
  <span style="display:block;">速く、軽く、</span>
  <span style="display:block;">ライブラリ不要。</span>
</h1>

行は spanp で分けてください。親の reveal--lines が順番制御します。


5-2. 下線ドロー

使用シーン: キーワード強調、リンク風見出し

Scroll Reveal

HTML:

<p>
  大事なのは
  <span class="reveal reveal--underline">スクロール体験</span>
  です。
</p>

6. 画像系(2パターン)

6-1. ワイプリビール

使用シーン: 実績写真、Before/After、ヒーロー下のビジュアル

HTML:

<figure class="reveal reveal--wipe" style="overflow:hidden; margin:0;">
  <img src="/images/work.jpg" alt="制作実績" style="display:block; width:100%; height:auto;" />
</figure>

6-2. ケンバーンズ風ズーム

使用シーン: ヒーロー画像、ストーリー写真

HTML:

<figure class="reveal reveal--kenburns" style="overflow:hidden; margin:0;">
  <img src="/images/hero.jpg" alt="" style="display:block; width:100%; height:auto;" />
</figure>

親が is-inview になると、中の img がゆっくりズームアウトします。


7. 便利モディファイア(3パターン)

バリエーションクラスと組み合わせて使います。

7-1. 遅延付き

使用シーン: 同じ行の複数要素をずらして出す

now
+0.2s
+0.35s

HTML:

<div class="reveal reveal--up">すぐ出る</div>
<div class="reveal reveal--up reveal--delay-2">少し遅れて出る</div>
<div class="reveal reveal--up reveal--delay-3">さらに遅れて出る</div>

7-2. 速度変更

使用シーン: 短いUIは速く、大きなビジュアルはゆっくり

HTML:

<div class="reveal reveal--up reveal--fast">サクッと</div>
<div class="reveal reveal--up reveal--slow">ゆったり</div>

7-3. 繰り返し(画面外に出たら再隐藏)

使用シーン: デモページ、スクロール体験を何度も見せたいLP

HTML:

<section class="reveal reveal--up reveal--repeat">
  画面に入るたび再生
</section>

通常は一度きり(unobserve)の方がパフォーマンスもUXも良いです。繰り返しは必要な場所だけに使ってください。


実践レシピ:よくある組み合わせ

カードグリッド

<div class="cards reveal reveal--stagger">
  <article>カード1</article>
  <article>カード2</article>
  <article>カード3</article>
</div>

左右交互の特徴紹介

<section class="reveal reveal--left">左テキスト + 右画像</section>
<section class="reveal reveal--right reveal--delay-1">右テキスト + 左画像</section>

見出し → 本文 → CTA

<h2 class="reveal reveal--up">見出し</h2>
<p class="reveal reveal--up reveal--delay-1">説明文</p>
<a class="reveal reveal--up reveal--delay-2" href="/contact">お問い合わせ</a>

付録A:CSSだけで動かす(モダンブラウザ)

Chrome / Edge / 新しいSafariでは、JSなしの Scroll-Driven Animations も使えます。Firefoxは未対応なので、本記事の本命は IntersectionObserver 方式です。対応ブラウザ向けのおまけとして置きます。

@media (prefers-reduced-motion: no-preference) {
  @supports ((animation-timeline: view()) and (animation-range: entry)) {
    @keyframes reveal-up {
      from {
        opacity: 0;
        transform: translateY(32px);
      }
    }

    .reveal-css {
      animation: reveal-up ease both;
      animation-timeline: view();
      animation-range: entry 0% entry 40%;
    }
  }
}
<section class="reveal-css">CSSだけで下から出現</section>

ポイント:

  • animation のあとに animation-timeline / animation-range を書く(短縮記法で上書きされないように)
  • 装飾目的なら、未対応ブラウザでは何も動かさず最初から表示、でもよい(プログレッシブエンハンスメント)

付録B:つまずきポイント

動かないとき

  1. .reveal が付いているか
  2. reveal.js が読まれているか(defer 推奨)
  3. 親に overflow: hidden がありすぎて、発火前にクリップされていないか
  4. prefers-reduced-motion: reduce の環境では最初から表示される(仕様どおり)

チラつき・ガタつきを減らす

  • 動かすのは opacity / transform / filter / clip-path に限定
  • 同時に大量の .reveal を画面内に置かない
  • 画像は width / height かアスペクト比を指定してレイアウトシフトを防ぐ

WordPress / ノーコードでも使えるか

使えます。テーマやカスタムHTMLブロックにCSS/JSを足し、要素にクラスを付けるだけです。React / Next.js の場合は、クライアント側で同じObserverを一度初期化すればOKです。

"use client";
import { useEffect } from "react";

export function RevealInit() {
  useEffect(() => {
    // reveal.js と同じ処理をここに置くか、スクリプトを読み込む
  }, []);
  return null;
}

まとめ

本記事では、ライブラリなしで使えるスクロールリビールを20パターン紹介しました。

覚えることは3つだけ

  1. 共通CSS + 十数行JSを1回入れる
  2. 動かしたい要素に reveal + バリエーションクラスを付ける
  3. 遅延・速度・繰り返しはモディファイアで足す

選び方の目安

目的おすすめ
無難に上品reveal--up / reveal--fade
カード一覧reveal--stagger
写真を印象的にreveal--wipe / reveal--kenburns
見出しを強くreveal--clip-up / reveal--lines
遊びを出すreveal--blur / reveal--flip

ボタンの見た目を整えたい場合は、あわせて【コピペOK】HTMLとCSSで作る実用的なボタンデザイン集24選もどうぞ。UI部品とスクロール演出をセットで入れると、LPの完成度が一気に上がります。

西村 力也

西村 力也

代表取締役

2002年からWeb制作・システム開発に従事。React、Next.js、TypeScriptを中心としたモダンなフロントエンド開発の専門家。AI検索最適化(AIO)の先駆者として、ChatGPT、Perplexity等のAI検索エンジン対応を推進。三重県津市を拠点に、東海地方の企業様のデジタル変革を支援しています。

React/Next.js開発TypeScriptAI検索最適化(AIO)SEO/MEO対策