1实现原理 · 为什么它能做到
把 prefers-reduced-motion 当分级降级而非开关:先把动画分三档(1 移除 / 2 软化 / 3 保留),再按档改 CSS 与 JS
skills/accessible-animation/SKILL.md
Honor `prefers-reduced-motion: reduce` as a *graceful degradation*, not a kill switch.
这解释了它为什么比一句 animation: none !important 复杂:全关会造成元素瞬移与状态提示(进度、焦点环)缺失。
CSS 层:全局兜底用 0.01ms(保留 transitionend/animationend 事件)+ animation-iteration-count: 1 杀掉无限旋转,并用肯定式查询 no-preference 把运动选择性打开
skills/accessible-animation/SKILL.md
which can break JS that waits for transitionend/animationend. Use 0.01ms.
两处细节都来自实战踩坑:0s 会让等待事件的 JS 卡死;无限跑马灯在近零时长下仍占 CPU。
JS 层:CSS 管不到 GSAP/canvas/Lenis,统一用 matchMedia 加 change 监听实时响应,并给可复用的 useReducedMotion hook
skills/accessible-animation/SKILL.md
CSS cannot gate JS-driven animation (GSAP timelines, Framer's `animate`, canvas/WebGL, Lenis).
三份库级配方(gsap.matchMedia、Framer Motion reducedMotion、Lenis 干脆不实例化)各自对应不同的回滚语义。
把要求锚到 WCAG 条款(2.3.3 AAA / C39 / 2.2.2 A),并强制验收时同时截正常路径与降级路径
skills/accessible-animation/SKILL.md
npx playwright screenshot --reduced-motion=reduce --wait-for-timeout=500 "file://$PWD/demo.html?t=0.6&reduce=1" reduced.png
?reduce=1 与 --reduced-motion=reduce 双通道,解决 CSS 层无法从 JS 切换的取证难题。
2核心能力
01三档运动分级(Tier 1 移除 / Tier 2 软化 / Tier 3 保留)与逐项判据
02CSS 全局安全网加分层次覆盖(避免全局 * 覆盖掉 Tier 3 运动)
03JS 侧 matchMedia 门控与运行时变更监听(OS 开关实时生效)
04React useReducedMotion hook(含 SSR 水合不同步的处理)
05库级配方:GSAP matchMedia 自动回滚 / Framer Motion reducedMotion / Lenis 不实例化
06WCAG 映射(2.3.3 Animation from Interactions / C39 / 2.2.2 Pause, Stop, Hide)
07双路径取证(正常与降级各截一帧)与 5 条完成前清单
08应用级一键降级(Framer Motion 的 MotionConfig reducedMotion="user")
09零 build 交付(单 HTML 内联 CSS 与 JS 或走 CDN,明确不要 bundler)
3外部依赖
| Kind | Dependency / Endpoint |
|---|---|
| cli | npx / Playwright(宿主侧截图工具,带 --reduced-motion=reduce 开关;非 skill 自带) |
| cli | scripts/seek-shot.sh + scripts/contact-sheet.sh(仓库根打包助手;SKILL.md 的 Packaged helper 段点名) |
| cli | ffmpeg(contact-sheet.sh 用 hstack 拼接触表) |
| package | gsap(可选示例:gsap.matchMedia 条件回滚) |
| package | lenis(可选示例:降级路径下不实例化平滑滚动) |
| package | framer-motion(可选示例:自带 useReducedMotion) |
| api | window.matchMedia('(prefers-reduced-motion: reduce)') 与 MediaQueryList 的 change 事件 |
4管控建议与判定依据
建议配套管控措施
面向 Agent
限定工作目录
面向管理者
保留操作记录
判定依据(文件路径与关键语句摘要)
- 本地工作目录: 文件读写与工件输出: 本 skill 目录零写盘;交付物为 1 个自包含 .html(含正常与降级两条路径),由 agent 写出
审计说明: 。判级只依据 skill 自身目录(skills/accessible-animation/ = SKILL.md + 0 字节 README.md + references/patterns.md,find 全量核对):零脚本、零凭证、零执行期外发(token 扫描 fetch(/XMLHttpRequest/curl/wget/child_process/process.env/API_KEY|TOKEN|SECRET/.env/eval( 零命中)、无写盘。正文点名的外部物是宿主侧截图工具 npx playwright(含 --reduced-motion=reduce 开关)与可选 npm 包(gsap/lenis/framer-motion,写在示例代码里、由用户项目安装),均非本 skill 自带行为;交付 HTML 若引 CDN 属产物期引用,不判级。
5第二遍独立确认
- [ok] --reduced-motion=reduce 是否真是可用的取证开关(否则验收步骤失效) — SKILL.md 与 references 都用它驱动验收,同时提供不依赖该 CLI 的替代(?reduce=1 加浏览器工具模拟媒体特性),因此验收路径不唯一依赖该开关;本次只读侦查未实际运行该命令,故仅确认文档层面自洽。
- [ok] 0.01ms 而非 0s 的理由是否成立 — SKILL.md 正文与 Gotchas 两处一致说明:0s 会让等待 transitionend/animationend 的 JS 收不到事件;references 的全局兜底同样使用 0.01ms,前后自洽。
- [ok] WCAG 条款号与级别是否与正文一致 — 2.3.3(AAA,交互触发运动)、C39(命名充分技术)、2.2.2(A,超过 5s 的自动运动需可暂停)三处在 WCAG mapping 段、速查表与 Gotchas 互相印证,未见错配。
- [discrepancy] Packaged helper 的相对路径基准 — SKILL.md 写 scripts/seek-shot.sh anim.html 0 1.5 3,但 scripts/ 位于仓库根而非本 skill 目录,单装形态下相对路径不成立(对 pin commit 有效的真实出入)。
6结论
适合: 适合:① 给已有动效做无障碍整改(用户反馈眩晕或审计出 WCAG 问题);② 设计阶段就把 reduced-motion 分级写进组件规范的团队;③ 需要同时管住 CSS 与 GSAP/Framer/Lenis/canvas 多套动效源的工程;④ 需要一份能拿两份截图交差的演示与验收脚本。
不适合: 不适合:① 只想让动画更好看的诉求(本 skill 只谈降级与合规);② 完整 a11y 审计(颜色对比、焦点顺序、ARIA 不在范围内,只覆盖运动);③ 用它替代 glassmorphism 或 60fps-animation——本 skill 只管动多少,不管怎么动得好看或便宜。
Install Agent-Ready
① Verified Mirror 2026-09-28
Option A · Direct DownloadDownload accessible-animation.tar.gz
sha256:
Option B · Copy Guide for Agent490eb34e2446669d…agent 读 JSON 指南后会自动从本站下载安装,无需更多说明。
② Upstream GitHub
GitHub Repo ↗
Pinned to commit b6dba3eb75.