DEMO
SCROLL ME ↓
CODE
<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>
.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
要素が画面に入ってきたらフェードインするスクロールリビールを、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
※当サイトはAmazonアソシエイトプログラムの参加者です。リンクから商品をご購入いただくと、当方に紹介料が発生します。
学びを止めない · AMAZONサブスク
※当サイトはAmazonアソシエイトプログラムの参加者です。リンクから商品をご購入いただくと、当方に紹介料が発生します。
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プロンプトは、クレジット表記なしで自由に使えます。コピーしてそのままプロジェクトに利用できます。