mcpField
C
css-scroll-driven-native

css-scroll-driven-native

github.com/rheinmirDesign & UI1075 installsUpdated 2w ago
Repository

About css-scroll-driven-native

css-scroll-driven-native is a skill for adding scroll-linked effects with native CSS timelines and no JavaScript. It is intended for progressive enhancement, with static visible-content fallbacks and reduced-motion safeguards.

Key features

  1. 01CSS scroll() and view() timelines
  2. 02Progress, reveal, and parallax effects
  3. 03@supports static fallback guidance
  4. 04Reduced-motion safeguards
  5. 05Playwright visual verification

Use cases

  1. 01Adding a page-scroll progress bar
  2. 02Revealing cards as they enter view
  3. 03Creating lightweight parallax effects

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/rheinmir/setup --skill css-scroll-driven-native

After installing, type/css-scroll-driven-nativein Claude Code to confirm it loaded.

Bundled filesassets/demo.cssassets/demo.html

Details

From the project README

Skill: css-scroll-driven-native

Hiệu ứng cuộn trang bằng CSS spec công khai — animation-timeline: scroll() / view() + animation-range — không một dòng JavaScript.

WHAT

Purpose và context
  • Purpose: thêm hiệu ứng cuộn (progress bar, reveal-on-view, parallax nhẹ) bằng CSS thuần animation-timeline làm progressive enhancement — trình duyệt chưa hỗ trợ hoặc bật reduce-motion vẫn thấy đủ nội dung tĩnh.
  • Trigger (when to use): user nói "css scroll driven animation", "animation-timeline", "scroll animation không js", "css thuần cuộn trang", "scroll-driven CSS", hoặc /css-scroll-driven-native; hoặc muốn thêm "độ mượt" 0-JS phía trên scroll-effects. Chọn theo bảng "Khi nào chọn cái này vs scroll-effects" (mục Reference).
  • Non-goals: không phải cơ chế chính khi cần chạy chắc production đa trình duyệt ngay (đó là scroll-effects, JS IntersectionObserver); không viết JS; không cứng số phiên bản trình duyệt.
Mental model

timeline (scroll(root) | view()) + animation-range → keyframes; toàn bộ nằm trong @supports → @media not (prefers-reduced-motion: reduce); ngoài hai khối đó = trạng thái tĩnh hiện đủ nội dung.

Input và output contract
FieldRequired?Ý nghĩa
Incơ chế cần (progress / reveal / parallax)cóchọn 1–3 trong 3 cơ chế
Indesign.md của dự ánkhôngcó thì đổi token màu/spacing theo nó
OutCSS (+ markup tối thiểu) adapt từ assets/demo.css / assets/demo.htmlcómọi animation trong @supports + reduce-motion guard
Outbằng chứng verifycóảnh 0%/50%/100% scroll + ảnh reduce-motion qua playwright-verify
Rules và capabilities

Rules (BẮT BUỘC):

  • RULE-01 (MUST): Luôn có fallback @supports: mọi animation nằm trong @supports (animation-timeline: scroll()) hoặc @supports (animation-timeline: view()). Bên NGOÀI khối @supports là trạng thái TĨNH mặc định — phần tử hiện đủ nội dung, không animation, KHÔNG BAO GIỜ ẩn/opacity:0 làm mặc định. Nếu viết opacity:0 cho hiệu ứng reveal, giá trị đó CHỈ được đặt bên trong @supports, không phải ở rule gốc.
  • RULE-02 (MUST): prefers-reduced-motion: bọc animation trong @media not (prefers-reduced-motion: reduce) (lồng bên trong @supports, xem demo.css). Người dùng bật reduce-motion → mọi phần tử về trạng thái tĩnh giống hệt trình duyệt không hỗ trợ.
  • RULE-03 (MUST): KHÔNG cứng số phiên bản vào code hay comment — kiểm tra caniuse.com/css-scroll-driven-animations mỗi lần dùng thật (bảng hỗ trợ ở mục Reference).
  • RULE-04 (MUST): animation-duration vẫn phải khai (1ms hoặc giá trị bất kỳ >0) dù thời lượng thật do timeline điều khiển — một số engine yêu cầu giá trị này để kích hoạt animation.
  • RULE-05 (MUST): Verify bằng playwright-verify trên trình duyệt Chromium (CDP mặc định hỗ trợ scroll-driven animations): chụp ảnh tại 0%/50%/100% scroll, assert progress bar/scaleX và card opacity đổi theo vị trí cuộn; đồng thời chụp thêm với prefers-reduced-motion: reduce giả lập (Playwright emulateMedia) để assert KHÔNG animation nhưng nội dung vẫn hiện đủ.
  • Capabilities: đọc asset skill + design.md; ghi CSS/HTML vào dự án đích; chạy trình duyệt Chromium headless có giả lập media.
Failure boundaries
  • Yêu cầu "phải chạy chắc trên mọi trình duyệt ngay" → clarify/chuyển scroll-effects làm nền, skill này chỉ override.
  • Nội dung bị ẩn khi @supports sai hoặc reduce-motion bật → failed (vi phạm RULE-01/02), sửa trước khi giao.
  • Ảnh 0%/50%/100% giống hệt nhau trên Chromium → failed (animation không kích hoạt, thường thiếu animation-duration).

HOW

Main workflow
StepTypeInputsActionOutputs/exitFailure/next
W01judgmentyêu cầu + đích trình duyệtChọn skill này hay scroll-effects theo bảng so sánh; kiểm caniusequyết địnhcần chắc đa trình duyệt → B01
W02deterministicassets/demo.*Đọc assets/demo.html + assets/demo.css, lấy cơ chế cầnsnippet—
W03effectsnippet, design.mdADAPT token màu/spacing; đặt animation trong @supports + reduce-motionCSS trong dự án—
W04deterministictrang đã gắnVerify RULE-05: chụp 0/50/100% + emulateMedia reduceảnh + assertassert đỏ → sửa, lặp W04
Branches
IDKindGuardHành viSkip / failureRejoin
B01user_optionalcần chạy chắc đa trình duyệt nhưng vẫn muốn 0-JS mượt hơnkết hợp: scroll-effects làm nền, skill này override khi trình duyệt hỗ trợchỉ cần Chromium → skipW02
Validation và stopping

Assert tất định ở W04 (scaleX/opacity đổi theo vị trí cuộn; reduce-motion không animation, nội dung đủ). Cần mắt: độ mượt/hợp design. Dừng khi hai loại ảnh đều đạt; 2 vòng vẫn đỏ → báo user kèm ảnh.

Examples
  • Positive: "thêm progress bar đọc bài bằng css thuần" → .csdn-progress với animation-timeline: scroll(root) trong @supports + reduce-motion guard → ảnh 0%/50%/100% cho scaleX 0 → ~0.5 → 1.
  • Boundary/failure: reveal card đặt opacity:0 ở rule gốc → trên Firefox chưa hỗ trợ card biến mất → vi phạm RULE-01, chuyển opacity:0 vào trong @supports rồi verify lại với reduce-motion.
Reference — Khi nào chọn cái này vs scroll-effects
css-scroll-driven-native (skill này)scroll-effects
JS0 dòngIntersectionObserver + rAF
Hỗ trợ trình duyệtChrome/Edge tốt; Firefox/Safari đang rollout, có thể chưa bật mặc địnhMọi trình duyệt hiện đại
Khi dùngProgressive enhancement — thêm "độ mượt" cho trình duyệt đã hỗ trợ, KHÔNG phải cơ chế chính nếu cần chạy chắc production đa trình duyệt ngayCơ chế chính khi cần chạy chắc ngay, không đợi rollout

Khuyến nghị: dùng skill này bên trong @supports (animation-timeline: scroll()), fallback tĩnh (không animation, không ẩn nội dung) — hoặc kết hợp cả hai: scroll-effects làm nền, skill này override khi trình duyệt hỗ trợ.

⚠️ Kiểm tra hỗ trợ thật trước khi dùng production tại caniuse.com/css-scroll-driven-animations — đừng tin số liệu cứng ghi trong tài liệu này, API đang rollout nhanh và bảng hỗ trợ có thể đã đổi.

Bảng hỗ trợ trình duyệt hiện tại (ghi tại thời điểm viết skill, 2026-09 — có thể đã đổi, luôn tự kiểm tra):

Trình duyệtanimation-timeline: scroll()animation-timeline: view()
Chrome / EdgeCóCó
FirefoxBehind flag / đang rolloutBehind flag / đang rollout
SafariĐang rollout, chưa ổn địnhĐang rollout, chưa ổn định
Reference — Assets

assets/demo.html + assets/demo.css — 3 cơ chế demo, đọc rồi ADAPT (đổi token màu/spacing theo design.md của dự án nếu có). Mở trực tiếp bằng trình duyệt hỗ trợ (Chrome/Edge mới) để xem chạy thật; trình duyệt chưa hỗ trợ sẽ tự rơi về trạng thái tĩnh.

Reference — 3 cơ chế (markup tối thiểu + cơ chế)
1. Progress bar theo cuộn trang

Thanh cố định trên cùng, dài theo % đã cuộn hết trang.

<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) bám vào tiến độ cuộn của toàn trang — không cần scroll listener, không cần tính scrollY / scrollHeight bằng tay.

2. Reveal-on-view khi phần tử vào khung nhìn
<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() là timeline riêng của TỪNG phần tử theo vị trí trong viewport của chính nó — thay hẳn IntersectionObserver. animation-range: entry 0% cover 40% nghĩa là animation chạy từ lúc phần tử bắt đầu vào viewport (entry 0%) tới khi đã "cover" 40% quãng đường qua viewport.

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.

Comments

Markdown supported