已使用Intersection Observer API,如何用纯CSS实现元素每次入视动画?
纯CSS实现元素进入视口时的重复动画效果
完全可以用纯CSS搞定这个需求,不用写JavaScript。现在主流浏览器都支持滚动驱动动画,能精准控制元素每次进入屏幕时触发动画,而且支持重复触发——每次元素滚回视口都会重新执行动画。
方法1:用标准滚动驱动动画(animation-timeline)
这是现在最推荐的方案,符合CSS最新标准,兼容性也不错(Chrome 115+、Firefox 117+、Safari 17+)。
代码示例
HTML
<div class="container"> <div class="animate-item">元素1</div> <div class="animate-item">元素2</div> <div class="animate-item">元素3</div> <div class="animate-item">元素4</div> </div>
CSS
/* 给容器加足够高度,方便滚动测试 */ .container { height: 200vh; display: flex; flex-direction: column; gap: 100vh; align-items: center; justify-content: center; } .animate-item { width: 200px; height: 200px; background: #4285F4; color: white; display: flex; align-items: center; justify-content: center; font-size: 20px; /* 初始状态:透明+向下偏移 */ opacity: 0; transform: translateY(50px); /* 定义动画 */ animation: fadeInUp 0.6s ease forwards; /* 把动画绑定到视口滚动 */ animation-timeline: view(); /* 设置触发时机:元素刚进入视口时启动,完全进入后结束 */ animation-range: entry 0% entry 100%; } /* 动画关键帧 */ @keyframes fadeInUp { to { opacity: 1; transform: translateY(0); } }
这里animation-timeline: view()让动画跟着视口滚动走,animation-range指定了动画触发的滚动范围——元素开始进入视口时启动动画,完全进入时完成。每次元素滚回视口,动画都会重新跑一遍。
方法2:用@scroll-timeline(旧语法,兼容老版本浏览器)
这是早期的滚动时间线写法,部分旧版Chrome/Firefox支持,现在慢慢被标准语法替代,但如果要兼容更老的浏览器可以用:
CSS示例
@scroll-timeline fadeInTimeline { source: selector(.container); orientation: vertical; scroll-offsets: selector(.animate-item) entry 0%, selector(.animate-item) entry 100%; } .animate-item { /* 初始状态同上 */ opacity: 0; transform: translateY(50px); animation: fadeInUp 0.6s ease forwards; animation-timeline: fadeInTimeline; } @keyframes fadeInUp { to { opacity: 1; transform: translateY(0); } }
注意点
- 兼容性:标准滚动驱动动画在现代浏览器里支持很好,但如果要兼容IE或者Chrome 115以下的版本,还是得用回Intersection Observer的方案。
- 重复触发:上面的方案默认就是每次元素进入视口都触发动画,不用额外设置。如果只想触发一次,加个
animation-iteration-count: 1就行,但默认是重复触发的。 - 自定义触发时机:可以调整
animation-range的值来改动画启动的时机,比如entry 20%就是元素进入视口20%的时候开始动画。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

