关于 scroll-scrubbed-word-reveal
面向网页动效实现的设计技能,将滚动进度映射为逐词显现,同时保留原始文本、内联语义和可访问性。提供 DOM 处理、动效映射、减弱动态效果支持及清理验证指引。
主要功能
- 01保留可访问的原始文本
- 02遍历文本节点拆分词语
- 03按滚动进度逐词显现
- 04支持 GSAP ScrollTrigger 或原生滚动
- 05兼顾减少动态效果与清理
适用场景
- 01为文章段落添加滚动显现效果
- 02在保留链接和强调语义时制作文本动效
- 03验证响应式、辅助技术与反向滚动体验
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mengto/ skills --skill scroll-scrubbed-word-reveal安装后在 Claude Code 中输入/scroll-scrubbed-word-reveal确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
REFERENCES.mdagents/openai.yamldemo/index.htmlPROMPT.md详细介绍
滚动驱动的逐词显现
让阅读进度清晰可见,同时不替换真实文本、不破坏行内标记,也不依赖固定的行数。
准备文本
- 在 DOM 中保留一份未经修改且可访问的文本源。
- 使用
TreeWalker遍历文本节点;不要用textContent或innerHTML扁平化容器。 - 跳过
script、style、表单控件和带有[data-no-split]标记的元素。 - 仅将非空白词元替换为 span,并原样保留空白节点。
- 仅当仍有一份等效的、未拆分且可访问的副本时,才将生成的 span 标记为
aria-hidden="true"。
首选结构:
<p class="reveal" data-reveal>
Motion should <em>explain</em> the next state, not decorate it.
</p>
避免按行拆分。浏览器换行必须能够随容器宽度、语言、缩放和字体加载自由变化。
将滚动映射到单词
将区段进度作为唯一事实来源:
const reveal = Math.min(1, Math.max(0, progress));
const local = Math.min(1, Math.max(0, reveal * wordCount - index));
word.style.setProperty("--word-progress", local);
根据 --word-progress 插值设置隐藏状态的透明度、模糊和垂直偏移。让可见状态与普通排版完全一致。
需要精确控制起点、终点、刷新或共享时间线时,使用带有 scrub 的 GSAP ScrollTrigger。对于独立区段,可使用无依赖的滚动测量加 requestAnimationFrame。
设置实用的默认值
- 隐藏状态透明度:
0.12–0.3 - 模糊:
4–10px - 垂直偏移:
0.08–0.22em - 段落的显现跨度:视口高度的
120–220% - 直接单词重叠:
10–30% - 缓动:滚动映射不使用缓动;仅在需要时对视觉插值使用缓动
将这些值设为 CSS 自定义属性。根据文本长度调整滚动跨度,不要假设所有段落都适用相同的时长。
保留强调样式
- 保留链接、
strong、em、mark 和强调 span 的语义与样式。 - 默认使用继承的颜色;在原始元素上设置强调样式,而不是基于词元索引设置。
- 不要只在悬停时或读者经过之后才显示重要链接。
- 仅当源文本发生变化时才重新拆分。响应式换行不需要重新构建词元。
- 保存足够的状态,以便在清理时还原原始 DOM。
保持可读性
- 使用真实的文档流;只有当文案和依据足以支持一个短暂且刻意安排的阅读停顿时,才使用固定定位。
- 除非用户明确要求,否则不要使用打字机光标、随机延迟或自动播放。
- 在
prefers-reduced-motion: reduce下,立即显示所有单词,移除模糊和变换,并取消任何固定定位。 - 保持屏幕阅读器的朗读自然,避免逐词播报。
- 检查隐藏状态和最终状态下的对比度;隐藏单词可以较不醒目,但最终文本必须符合常规阅读要求。
清理
在路由切换或组件卸载时,销毁 ScrollTrigger,移除滚动和调整大小的监听器,取消动画帧,并还原原始标记子树。如果起点或终点取决于文本几何尺寸,则在字体加载后刷新测量值。
验证
测试行内链接和强调样式、标点、重复空格、长单词、200% 缩放、390/768/1440 宽度、内容变化、向前和向后滚动、减少动态效果、键盘焦点、屏幕阅读器朗读顺序,以及拆除流程。即使禁用 JavaScript,最终 DOM 仍必须能表达完整句子。
使用 demo/index.html 作为实践参考,并使用 demo/PROMPT.md 重新创建或改编示例。将 REFERENCES.md 作为仅包含链接的实现来源列表。