No.117
SCROLL CSS

Scroll Reveal View Timeline

animation-timeline: view() で要素が画面に入ると同時にフェードインさせるCSSオンリー実装。IntersectionObserver は不要。

DEMO

SCROLL ME ↓

01VIEW TIMELINE
02NO JAVASCRIPT
03ENTRY RANGE
04GPU FRIENDLY
05PROGRESSIVE

CODE

HTML
<div class="demo-stage svt-stage">
  <div class="svt-scroller">
    <p class="svt-hint">SCROLL ME ↓</p>
    <div class="svt-item"><span class="svt-num">01</span>VIEW TIMELINE</div>
    <div class="svt-item"><span class="svt-num">02</span>NO JAVASCRIPT</div>
    <div class="svt-item"><span class="svt-num">03</span>ENTRY RANGE</div>
    <div class="svt-item"><span class="svt-num">04</span>GPU FRIENDLY</div>
    <div class="svt-item"><span class="svt-num">05</span>PROGRESSIVE</div>
  </div>
</div>
CSS
.svt-stage { position:relative; min-height:280px; background:#0F0F12; padding:0; overflow:hidden; }
.svt-scroller { height:320px; overflow-y:auto; padding:1.5rem 2rem 3rem; }
.svt-hint { font-family:'Oswald',sans-serif; font-size:.72rem; letter-spacing:.28em; color:#E91B89; margin-bottom:1.5rem; }
.svt-item {
  display:flex; align-items:center; gap:1rem;
  padding:1.4rem 1.6rem; margin-bottom:1.2rem;
  background:#17171C; border:1px solid rgba(255,255,255,.08); border-radius:10px;
  color:#EDEDED; font-family:'Oswald',sans-serif; font-size:1rem; letter-spacing:.12em;
}
.svt-num { color:#E91B89; font-size:.8rem; letter-spacing:.2em; }
@supports (animation-timeline: view()) {
  .svt-item {
    animation: svt-in linear both;
    animation-timeline: view();
    animation-range: entry 5% cover 32%;
  }
}
@keyframes svt-in {
  from { opacity:0; transform:translateY(28px) scale(.97); }
  to   { opacity:1; transform:none; }
}
@media (prefers-reduced-motion: reduce) {
  .svt-item { animation:none; opacity:1; transform:none; }
}

AI PROMPT

Claude Code Cursor v0
PROMPT
要素が画面に入ってきたらフェードインするスクロールリビールを、IntersectionObserver を使わずCSSだけで作って。対象要素に animation-timeline: view(); を指定すると、その要素自身がスクロールポート内を通過する進捗がアニメーションの再生位置になる。animation-range: entry 5% cover 32%; のように「どの区間で再生し切るか」を指定するのが要点で、entry は要素が入り始めてから完全に入るまで、cover は要素が可視領域と重なっている全区間を指す。keyframes は from { opacity: 0; transform: translateY(28px) } to { opacity: 1; transform: none } とし、animation-fill-mode は both(linear both)にする。必ず @supports (animation-timeline: view()) で囲み、非対応ブラウザでは opacity: 1 の通常表示が残るようにすること。複数要素に同じ指定をするだけで自動的に順番に出るので、遅延の手計算は不要。

Acceptance criteria: works with prefers-reduced-motion (animation disabled), zero console errors, zero layout shift

AIエージェントでの実装ガイド → Claude Code でWebアニメーションを実装する

BOOKS · PR · AMAZON

📖 なかしまぁ先生のCSSアニメーション入門 📖 UIデザインの教科書 新版 マルチデバイス時代のインターフェース設計 📖 Fundamentals of Web Animation with GSAP

※当サイトはAmazonアソシエイトプログラムの参加者です。リンクから商品をご購入いただくと、当方に紹介料が発生します。

学びを止めない · AMAZONサブスク

📚 Kindle Unlimited — 技術書・デザイン書が読み放題。30日無料体験 → 🎧 Audible — 移動中に耳で学ぶオーディオブック。30日無料体験 → 📦 Amazon Prime — Prime Reading・配送特典つき。30日無料体験 → 🎵 Music Unlimited — 作業用BGMに。1億曲が聴き放題・30日無料体験 →

※当サイトはAmazonアソシエイトプログラムの参加者です。リンクから商品をご購入いただくと、当方に紹介料が発生します。

RELATED EFFECTS

↗ MORE
→ SCROLL DRIVEN PROGRESS → SCROLL TRIGGER → GSAP SCROLL REVEAL

Scroll Reveal with View Timeline(view()によるスクロール出現)とは

animation-timeline: view() は、要素自身がスクロールポートを通過する進捗をアニメーションの再生位置に割り当てる指定です。従来は IntersectionObserver で交差を監視し、クラスを付け外しして CSS トランジションを起動する、という2段構えが必要でしたが、この仕様ではCSSの2行で完結します。

当サイトの Scroll Trigger は IntersectionObserver 版、GSAP Scroll Reveal は GSAP ScrollTrigger 版で、いずれも対応ブラウザを選ばず細かい制御ができる従来型です。本ページはそれらを CSS ネイティブに置き換える別テーマとして用意しています。スクロールを戻したときに再生も巻き戻る(=スクラブする)点が、クラス付与型との体感的な違いです。

animation-range の指定が体験を決めます。区間を長く取りすぎると「スクロールを止めた位置で中途半端に固まる」ため、entry から cover 30% 程度の短い区間で再生し切る設計が扱いやすくなります。

よくある質問

view() と scroll() の違いは何ですか?

scroll() はスクロールコンテナ全体のスクロール量を基準にします。ページ全体の読了バーのように「どこまでスクロールしたか」を測る用途です。view() は要素自身が可視領域を通過する進捗を基準にするため、「その要素が見えてきたら動かす」という従来 IntersectionObserver で書いていた処理に対応します。

animation-range はどう決めればよいですか?

entry は要素が下から入り始めてから完全に入り切るまで、exit は上へ抜け始めてから抜け切るまで、cover は重なっている全区間です。出現アニメーションなら entry 0%〜cover 30% 程度に収めると、要素が画面中央に来る前に再生が終わり自然に見えます。区間を長くしすぎると「スクロールを止めると途中で固まる」ので短めが基本です。

コードは無料で使えますか?

はい。Motion LabのコードスニペットとAIプロンプトは、クレジット表記なしで自由に使えます。コピーしてそのままプロジェクトに利用できます。