css-scroll-driven-native について
css-scroll-driven-nativeは、JavaScriptを使わずCSSのネイティブなタイムラインでスクロール連動効果を加えるスキルです。静的なフォールバックと動きを抑える設定を備えたプログレッシブエンハンスメント向けです。
主な機能
- 01CSS scroll()とview()のタイムライン
- 02進捗・表示・パララックス効果
- 03@supportsによる静的フォールバック指針
- 04視差効果を抑える設定
- 05Playwrightによる表示検証
活用シーン
- 01ページスクロールの進捗バー追加
- 02カードが画面内に入る際の表示
- 03軽量なパララックス効果の作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ rheinmir/ setup --skill css-scroll-driven-nativeインストール後、Claude Code で/css-scroll-driven-nativeを入力して読み込まれたか確認します。
同梱ファイルassets/demo.cssassets/demo.html
詳細
スキル:css-scroll-driven-native
公開CSS仕様を使ったスクロールエフェクト — animation-timeline: scroll() / view() + animation-range。JavaScriptは1行も使いません。
WHAT
目的とコンテキスト
- 目的: 純粋なCSSの
animation-timelineをプログレッシブエンハンスメントとして使い、スクロールエフェクト(プログレスバー、表示時のリビール、軽いパララックス)を追加します — 非対応ブラウザーやreduce-motionが有効な場合でも、静的な状態ですべてのコンテンツが表示されます。 - 使用するタイミング: ユーザーが「css scroll driven animation」「animation-timeline」「jsなしのスクロールアニメーション」「純粋なCSSでのページスクロール」「scroll-driven CSS」と言った場合、または/css-scroll-driven-nativeを指定した場合。または、
scroll-effectsの上に、0-JSで「滑らかさ」を追加したい場合。「これとscroll-effectsのどちらを選ぶか」の表(Referenceセクション)に従って選択してください。 - 対象外: 複数ブラウザーで本番環境ですぐ確実に動作させる必要がある場合の主要な仕組みではありません(その場合はJS IntersectionObserverを使う
scroll-effectsを使用します)。JSは書きません。ブラウザーのバージョン番号は固定しません。
メンタルモデル
timeline (scroll(root) | view()) + animation-range → keyframes; すべてを@supportsの中に配置し、さらに@media not (prefers-reduced-motion: reduce)で囲みます。これら2つのブロックの外側では、静的な状態ですべてのコンテンツが表示されます。
入力と出力の契約
| フィールド | 必須? | 意味 | |
|---|---|---|---|
| In | 必要な仕組み(progress / reveal / parallax) | はい | 3つの仕組みから1~3つ選択します |
| In | プロジェクトのdesign.md | いいえ | 存在する場合は、色や間隔のトークンをそれに合わせて変更します |
| Out | assets/demo.css / assets/demo.htmlを基にしたCSS(+ 最小限のマークアップ) | はい | すべてのアニメーションを@supportsとreduce-motionガードの中に配置します |
| Out | 検証の証拠 | はい | スクロール0%/50%/100%時の画像と、playwright-verifyで取得したreduce-motion時の画像 |
ルールと機能
ルール(必須):
- RULE-01 (MUST):必ず
@supportsによるフォールバックを設けてください:すべてのアニメーションを@supports (animation-timeline: scroll())または@supports (animation-timeline: view())の中に配置します。@supportsブロックの外側はデフォルトの静的状態とし、要素のコンテンツをすべて表示して、アニメーションは適用しません。デフォルトで要素を非表示にしたり、opacity:0にしたりしては絶対にいけません。リビールエフェクトにopacity:0を記述する場合、その値は@supports内にのみ設定し、元のルールには設定しないでください。 - RULE-02 (MUST):
prefers-reduced-motion:アニメーションを@media not (prefers-reduced-motion: reduce)で囲みます(@supportsの内側にネストします。demo.cssを参照)。ユーザーがreduce-motionを有効にした場合、すべての要素は非対応ブラウザーと同じ静的状態に戻ります。 - RULE-03 (MUST):コードやコメントにブラウザーのバージョン番号を固定で記述しないでください — 実際に使用するたびにcaniuse.com/css-scroll-driven-animationsを確認してください(Referenceセクションの対応表を参照)。
- RULE-04 (MUST):実際の時間はタイムラインで制御される場合でも、
animation-durationを指定する必要があります(1msまたは0より大きい任意の値)。一部のエンジンでは、アニメーションを有効にするためにこの値が必要です。 - RULE-05 (MUST):Chromiumブラウザー(CDPはデフォルトでスクロール駆動アニメーションに対応)で
playwright-verifyを使って検証してください。スクロール0%/50%/100%時の画像を撮影し、プログレスバー/scaleXとカードのopacityがスクロール位置に応じて変化することをアサートします。また、PlaywrightのemulateMediaでprefers-reduced-motion: reduceをエミュレートした状態でも画像を撮影し、アニメーションがない一方でコンテンツはすべて表示されていることをアサートします。 - 機能:スキルのアセットと
design.mdを読み取ります。対象プロジェクトにCSS/HTMLを書き込みます。メディア設定をエミュレートしたヘッドレスChromiumブラウザーを実行します。
失敗時の境界
- 「すべてのブラウザーですぐ確実に動作しなければならない」という要件がある場合 → 要件を確認する/ベースには
scroll-effectsを使用し、このスキルは上書きにのみ使用します。 @supportsの条件が満たされない場合やreduce-motionが有効な場合にコンテンツが非表示になる → 失敗(RULE-01/02違反)。引き渡し前に修正してください。- Chromiumで撮影した0%/50%/100%の画像がすべて同じ → 失敗(アニメーションが有効になっていません。多くの場合、
animation-durationが不足しています)。
HOW
主なワークフロー
| Step | Type | Inputs | Action | Outputs/exit | Failure/next |
|---|---|---|---|---|---|
| W01 | judgment | 要件 + ブラウザーの対象 | 比較表に基づいてこのスキルと scroll-effects のどちらを使うか選び、caniuse を確認します | 判断 | 複数ブラウザーでの確実な動作が必要 → B01 |
| W02 | deterministic | assets/demo.* | assets/demo.html + assets/demo.css を読み、必要な仕組みを取り出します | snippet | — |
| W03 | effect | snippet, design.md | 色/spacing のトークンを適応させます。@supports + reduce-motion の中にアニメーションを配置します | プロジェクト内の CSS | — |
| W04 | deterministic | 適用済みのページ | RULE-05 を検証します:0/50/100% のスクリーンショットを撮影 + emulateMedia reduce | 画像 + assert | assert が失敗 → 修正し、W04 を繰り返します |
分岐
| ID | Kind | Guard | 動作 | Skip / failure | Rejoin |
|---|---|---|---|---|---|
| B01 | user_optional | 複数ブラウザーでの確実な動作が必要だが、0-JS のスムーズさも高めたい | 組み合わせて使います:scroll-effects をベースにし、このスキルはブラウザーが対応している場合に上書きします | Chromium だけでよい → skip | W02 |
検証と停止条件
W04 では決定的な assert を行います(スクロール位置に応じて scaleX/opacity が変化する、reduce-motion ではアニメーションしない、コンテンツが十分に表示される)。目視で確認する項目:スムーズさ/デザインとの適合性。両方の種類の画像が合格したら停止します。2 回繰り返しても失敗する場合は、画像を添えてユーザーに報告します。
例
- 成功例:「CSS のみで記事の読書進捗バーを追加」→
@supports+ reduce-motion guard 内のanimation-timeline: scroll(root)を使った.csdn-progress→ scaleX が 0 → 約 0.5 → 1 となる 0%/50%/100% の画像。 - 境界/失敗例: reveal card のルートルールで
opacity:0を指定 → 未対応の Firefox ではカードが消える → RULE-01 違反です。opacity:0を@supportsの中に移し、reduce-motion でもう一度検証します。
参考 — これと scroll-effects のどちらを選ぶか
css-scroll-driven-native(このスキル) | scroll-effects | |
|---|---|---|
| JS | 0 行 | IntersectionObserver + rAF |
| ブラウザー対応状況 | Chrome/Edge では良好。Firefox/Safari では展開中で、既定ではまだ有効になっていない場合があります | すべてのモダンブラウザー |
| 使用場面 | プログレッシブエンハンスメント — 対応済みブラウザーに「スムーズさ」を追加します。複数ブラウザーの本番環境で今すぐ確実に動作させるための主要な仕組みではありません | 展開を待たず、今すぐ確実に動作する主要な仕組みが必要な場合 |
推奨:このスキルを @supports (animation-timeline: scroll()) の中で使い、静的なフォールバック(アニメーションなし、コンテンツを非表示にしない)を用意します。または両方を組み合わせます:scroll-effects をベースにし、このスキルはブラウザーが対応している場合に上書きします。
⚠️ 本番環境で使う前に、実際の対応状況を確認してください:caniuse.com/css-scroll-driven-animations — このドキュメントに記載された固定の数値を鵜呑みにしないでください。API は急速に展開中のため、対応状況の表は変更されている可能性があります。
現在のブラウザー対応状況(このスキルの執筆時点である 2026-09 の記録 — 変更されている可能性があります。必ずご自身で確認してください):
| ブラウザー | animation-timeline: scroll() | animation-timeline: view() |
|---|---|---|
| Chrome / Edge | 対応 | 対応 |
| Firefox | フラグで有効化/展開中 | フラグで有効化/展開中 |
| Safari | 展開中、まだ安定していません | 展開中、まだ安定していません |
参考 — アセット
assets/demo.html + assets/demo.css — デモ用の 3 つの仕組みです。読み込んでから適応させてください(プロジェクトに design.md がある場合は、それに合わせて色/spacing のトークンを変更します)。対応ブラウザー(新しい Chrome/Edge)で直接開くと、実際の動作を確認できます。未対応のブラウザーでは、自動的に静的な状態に戻ります。
参考 — 3 つの仕組み(最小限のマークアップ + 仕組み)
1. ページスクロール進捗バー
画面上部に固定され、ページ全体のスクロール済み割合に応じて長さが変わるバーです。
<div class="csdn-progress"></div>
.csdn-progress {
animation-name: progress-scale;
animation-duration: 1ms; /* giá trị bất kỳ để kích hoạt engine — thời lượng thật do timeline điều khiển */
animation-timeline: scroll(root);
animation-fill-mode: both;
}
@keyframes progress-scale {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
scroll(root) はページ全体のスクロール進捗に追従します — scroll リスナーも、scrollY / scrollHeight の手動計算も不要です。
2. 要素がビューポートに入ったときに表示
<article class="csdn-card">…</article>
.csdn-card {
animation-name: reveal-in;
animation-timeline: view();
animation-range: entry 0% cover 40%;
animation-fill-mode: both;
}
view() は、各要素が自身のビューポート内でどこにあるかに応じた個別のタイムラインです — IntersectionObserver を完全に置き換えます。animation-range: entry 0% cover 40% は、要素がビューポートに入り始めた時点(entry 0%)から、ビューポートを通過する経路の 40% を「cover」した時点までアニメーションが実行されることを意味します。
3. Parallax nhẹ dùng view()
Nền và nội dung dùng animation-range khác nhau trên cùng một timeline view() → tạo cảm giác lớp trôi khác tốc độ, không cần tính toán scrollY thủ công.
.parallax-bg { animation-timeline: view(); animation-range: cover 0% cover 100%; } /* trôi chậm, suốt cả quãng */
.parallax-content { animation-timeline: view(); animation-range: entry 0% cover 35%; } /* chạy nhanh, chỉ đoạn đầu */
Xem assets/demo.css mục 3 để có keyframes đầy đủ.
Origin
- Bổ sung cho
skills/scroll-effects(JS-based, chạy mọi trình duyệt) một lựa chọn 0-JS cho trình duyệt đã hỗ trợ — hai skill KHÔNG thay thế nhau, dùng theo bảng "Khi nào chọn cái này" ở trên.