写了五年滚动动画,每次入场都要写一整块 IntersectionObserver——今天 Chrome 145 用一个属性把这个彻底原生化了
写了五年滚动动画,每次入场都要写一整块 IntersectionObserver——今天 Chrome 145 用一个属性把这个彻底原生化了。
做过滚动reveal效果的前端都知道这个流程:写一个 IntersectionObserver,监听 N 个元素,每次回调里给元素加上 class,然后在 CSS 里写 transition。这套写法在项目里一躺就是几十行,调试的时候要同时翻 JS 和 CSS,还经常遇到 observer.disconnect() 漏写导致内存泄漏。
现在可以全删了。
Chrome 145 引入的 animation-trigger 属性,让浏览器自己在滚动时触发 CSS 动画的播放,不再需要一行 JavaScript。
具体怎么写?
旧写法(IntersectionObserver):
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('is-visible');
observer.unobserve(entry.target);
}
});
}, { threshold: 0.1 });
document.querySelectorAll('.reveal').forEach((el) => observer.observe(el));
CSS transition:
.reveal { opacity: 0; transform: translateY(40px); transition: all 0.6s ease-out; }
.reveal.is-visible { opacity: 1; transform: translateY(0); }
新写法(animation-trigger):
@keyframes reveal {
from { opacity: 0; transform: translateY(40px); }
to { opacity: 1; transform: translateY(0); }
}
.reveal {
animation: reveal 0.6s ease-out both;
animation-trigger: --fade-in play-forwards;
timeline-trigger-name: --fade-in;
timeline-trigger-source: view();
}
纯 CSS,零 JS。
animation-trigger 接收一个命名触发器,绑定 timeline-trigger-name 定义的名称,play-forwards 意思是进入触发范围时正向播放动画。和 IntersectionObserver 的区别在于:IntersectionObserver 只告诉你「元素过了阈值」,动画播放由你决定;animation-trigger 是浏览器在适当的时机自动触发播放,不需要任何 JS 介入。
还有一个关键区别。Scroll-driven animation(比如 animation-timeline: view())的进度条是和滚动位置强绑定的——滚动停止,动画就停在原地。animation-trigger 是「一次性触发」,触发了就开始按自己 duration 走,跟滚动是否继续无关。
play-forwards 之外还有几个动作:play-backwards(退出范围时反向播放)、pause(暂停)、reset(归零并暂停)、replay(归零重新播放)、play-once(触发一次后不再响应)。
浏览器支持情况:Chrome 145+ 已支持,Safari 和 Firefox 尚未实现,spec 目前还是 Editor’s Draft,正式标准之前语法可能还会有调整。生产环境使用建议加一个 @supports 降级:
@supports (animation-trigger: --x) {
.reveal { /* animation-trigger 版本 */ }
}
下一步怎么用?
- 把现有的 IntersectionObserver 滚动动画换成
animation-trigger,实测效果——Chrome 145+ 直接可用 - 配
trigger-scope做作用域隔离,避免同名触发器冲突 - 记得加
prefers-reduced-motion媒体查询,给减少动效需求的用户提供降级
这个属性的落地标志着 CSS 在交互控制上又往前走了一步:以前「进入视口触发」是 JS 的专属能力,现在浏览器把它原生接走了。
评论区
登录后可评论。