关于 masked-reveal
用于使用 GSAP 和 ScrollTrigger 制作错落式遮罩文字显现的设计技能。内容涵盖初始化、无障碍、清理和动效默认值,适用于短标题与章节引言。
主要功能
- 01滚动时让文字逐词显现
- 02使用 GSAP 设置逐词错落
- 03保留空格与无障碍文本
- 04支持减少动态效果及路由清理
适用场景
- 01为落地页标题添加动效
- 02滚动时显现章节引言
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mengto/ skills --skill masked-reveal安装后在 Claude Code 中输入/masked-reveal确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
demo/index.htmlPROMPT.mdsource.json详细介绍
遮罩揭示
适用场景
- 标题或简短文本块需要在滚动时呈现高级感的揭示效果。
- 文字应从不可见的遮罩中逐词上升,并按顺序错开出现。
- 项目已使用 GSAP,或需要基于 ScrollTrigger 的动效。
动效默认值
- 触发时机:文本顶部到达视口的
82%处时开始。 - 时长:
0.7s到0.9s。 - 错开间隔:每个词
0.025s到0.045s。 - 偏移:从
yPercent: 110到0。 - 缓动:
power3.out或expo.out。 - 重播:默认只揭示一次。
HTML
<h1 class="masked-reveal" data-masked-reveal>
Design systems that feel alive from the first scroll.
</h1>
CSS 遮罩
.masked-reveal {
visibility: visible;
}
html.js .masked-reveal[data-masked-reveal] {
visibility: hidden;
}
html.js .masked-reveal.is-split {
visibility: visible;
}
.masked-reveal .word-mask {
display: inline-block;
overflow: hidden;
vertical-align: top;
}
.masked-reveal .word {
display: inline-block;
transform: translateY(110%);
will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
html.js .masked-reveal[data-masked-reveal] {
visibility: visible;
}
.masked-reveal .word {
transform: none;
}
}
GSAP ScrollTrigger
这个辅助函数无需使用付费的 SplitText 插件,并能保留空格。
document.documentElement.classList.add("js");
gsap.registerPlugin(ScrollTrigger);
function escapeHTML(value) {
return value
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
function splitMaskedReveal(element) {
if (element.dataset.maskedRevealReady === "true") return;
const text = element.textContent.trim();
element.setAttribute("aria-label", text);
element.innerHTML = text
.split(/(\s+)/)
.map((part) => {
if (!part.trim()) return part;
return `<span class="word-mask" aria-hidden="true"><span class="word">${escapeHTML(part)}</span></span>`;
})
.join("");
element.dataset.maskedRevealReady = "true";
element.classList.add("is-split");
}
function initMaskedReveals(selector = "[data-masked-reveal]") {
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
document.querySelectorAll(selector).forEach((element) => {
splitMaskedReveal(element);
const words = element.querySelectorAll(".word");
gsap.set(element, { autoAlpha: 1 });
gsap.fromTo(
words,
{ yPercent: 110 },
{
yPercent: 0,
duration: 0.8,
ease: "power3.out",
stagger: 0.035,
scrollTrigger: {
trigger: element,
start: "top 82%",
once: true,
},
}
);
});
}
initMaskedReveals();
React 清理模式
useLayoutEffect(() => {
const ctx = gsap.context(() => {
initMaskedReveals("[data-masked-reveal]");
}, rootRef);
return () => ctx.revert();
}, []);
风格规则
- 用于简短标题、标签和章节引言;避免用于长段落。
- 保持垂直偏移干净利落。除非风格明确要求,否则不要搭配模糊效果。
- 按词而非按字母错开,营造更沉静的编辑风格。
- 如果换行至关重要,请在字体加载完成后再初始化。
- 图片延迟加载或布局发生偏移后,使用
ScrollTrigger.refresh()。 - 不要拆分包含链接、按钮或有意义的行内标记的文本。
快速检查
- GSAP 初始化前文本处于隐藏状态,随后通过
autoAlpha: 1显示。 - 屏幕阅读器通过
aria-label获取完整的原始文本。 - 单词之间的空格得以保留。
- 使用减少动态效果设置的用户会看到静态文本。
- 在 SPA 路由中清理 ScrollTrigger。
评论
支持 Markdown