DEMO
SCROLL ME
この枠の中をスクロールすると、上部のバーが伸びます。JavaScript は1行も使っていません。
スクロール量そのものをアニメーションの再生ヘッドに割り当てる CSS Scroll-driven Animations の機能です。
スクロールイベントを購読しないため、メインスレッドを止めずに滑らかに追従します。
記事ページの読了率バー、ランディングページの進捗インジケーターに使えます。
未対応のブラウザではバーが満タンのまま表示され、レイアウトは壊れません。
END
CODE
<div class="demo-stage sdp-stage">
<div class="sdp-scroller">
<div class="sdp-track"><div class="sdp-bar"></div></div>
<div class="sdp-content">
<p class="sdp-lead">SCROLL ME</p>
<p class="sdp-p">この枠の中をスクロールすると、上部のバーが伸びます。JavaScript は1行も使っていません。</p>
<p class="sdp-p">スクロール量そのものをアニメーションの再生ヘッドに割り当てる CSS Scroll-driven Animations の機能です。</p>
<p class="sdp-p">スクロールイベントを購読しないため、メインスレッドを止めずに滑らかに追従します。</p>
<p class="sdp-p">記事ページの読了率バー、ランディングページの進捗インジケーターに使えます。</p>
<p class="sdp-p">未対応のブラウザではバーが満タンのまま表示され、レイアウトは壊れません。</p>
<p class="sdp-end">END</p>
</div>
</div>
</div>
.sdp-stage { position:relative; min-height:280px; background:#0F0F12; padding:0; overflow:hidden; }
.sdp-scroller {
height:320px; overflow-y:auto; scroll-timeline: --sdp-scroll block;
}
.sdp-track {
position:sticky; top:0; z-index:2; height:4px; background:rgba(255,255,255,.08);
}
.sdp-bar {
height:100%; width:100%; transform-origin:0 50%;
background:linear-gradient(90deg,#E91B89,#7B37A8,#5BAADE);
}
@supports (animation-timeline: scroll()) {
.sdp-bar {
animation: sdp-grow linear both;
animation-timeline: --sdp-scroll;
}
}
@keyframes sdp-grow { from { transform:scaleX(0); } to { transform:scaleX(1); } }
.sdp-content { padding:2rem 2rem 3rem; }
.sdp-lead { font-family:'Oswald',sans-serif; font-size:.8rem; letter-spacing:.3em; color:#E91B89; margin-bottom:1.2rem; }
.sdp-p { font-size:.9rem; line-height:1.9; color:#B9B9C2; margin-bottom:1.4rem; }
.sdp-end { font-family:'Oswald',sans-serif; font-size:1.4rem; letter-spacing:.2em; color:#fff; padding-top:1rem; }
@media (prefers-reduced-motion: reduce) {
.sdp-bar { animation:none; transform:scaleX(1); }
}
AI PROMPT
JavaScriptを使わずに読了プログレスバーを作って。スクロールする要素に scroll-timeline: --名前 block; を宣言し、その子孫にあるバーへ animation-timeline: --名前; を指定する。バーのkeyframesは from { transform: scaleX(0) } to { transform: scaleX(1) } とし、transform-origin: 0 50% で左端起点に。バーは position: sticky; top: 0 のトラックに入れて常時見えるようにする。ページ全体で使う場合は scroll-timeline の宣言を省き animation-timeline: scroll() だけで document のスクロールに直結できる。重要: 非対応ブラウザで消えないよう、既定は transform: scaleX(1)(満タン)にしておき、@supports (animation-timeline: scroll()) の中だけで animation を当てること。scaleX なのでレイアウトを再計算せず、コンポジタスレッドで動くため軽い。
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アソシエイトプログラムの参加者です。リンクから商品をご購入いただくと、当方に紹介料が発生します。
スクロール量をそのままアニメーションの再生ヘッドに割り当てる CSS Scroll-driven Animations の最も基本的な使い方です。スクロールする要素に scroll-timeline を名付け、進捗バーに animation-timeline でその名前を渡すだけで、JavaScript のスクロールイベントを一切書かずに読了バーが完成します。
当サイトの Scroll Progress Bar は同じ見た目を JavaScript(scroll イベント+スクロール率の計算)で実装した従来型で、対応ブラウザを問わず動くのが強みです。本ページはそれを CSS だけに置き換えた新仕様版という別テーマになります。既存プロジェクトの置き換えを検討する場合は、両方を見比べてから選んでください。
実装で最も事故が多いのは「非対応ブラウザでバーが scaleX(0) のまま消える」パターンです。@supports で機能検出し、既定値を可視状態にしてから機能ブロック内でアニメーションを当てる、という順序を必ず守ってください。
Scroll-driven Animations とは何ですか?
スクロール量をアニメーションの再生位置に直結させるCSSの仕様です。従来は scroll イベントを購読してJavaScriptで進捗を計算していた処理を、animation-timeline: scroll() というCSSの1行に置き換えられます。イベント購読が不要なのでメインスレッドを塞がず、スクロールに完全同期した滑らかな動きになります。
対応していないブラウザではどうなりますか?
@supports (animation-timeline: scroll()) で囲っておけば、非対応ブラウザではアニメーションが適用されず、CSSで指定した既定の状態がそのまま表示されます。本ページのコードは既定を「バーが満タン」にしてあるため、非対応環境でも空欄や消失にはなりません。この既定値の設計が最も重要なポイントです。
コードは無料で使えますか?
はい。Motion LabのコードスニペットとAIプロンプトは、クレジット表記なしで自由に使えます。コピーしてそのままプロジェクトに利用できます。