如何在.active类每次激活时重复触发CSS动画?
解决图片滑块切换时CSS动画仅播放一次的问题
嘿,我来帮你搞定这个问题!你遇到的核心痛点是:CSS动画默认只会在元素首次渲染、样式首次应用时执行一次。当你的滑块切换,.active类转移到新元素上时,旧元素的动画已经跑完了,新元素因为动画属性一开始就存在,浏览器不会重新触发它。不过我们可以通过结合你提到的.play类来实现动画的重复播放,下面给你两种可行的方案:
方案一:JavaScript配合.play类重置动画
这种方法最直接可控,通过监听滑块切换事件,动态添加/移除.play类来强制触发动画:
步骤1:调整CSS,让动画仅在.play类生效时执行
把动画属性从基础样式中剥离,放到.play类里,这样只有当元素拥有这个类时才会播放动画:
.article.active { height: 75px; margin-top: -109px; margin-left: -70px; color: white; width: 100%; opacity: 0.8; z-index: 105; } .article-num { background: red; float: right; margin-top: 20px; width: 0; height: 32px; padding: 0; font-size: 27px; opacity: 0; } .article-num.play { animation-name: movingnum; animation-duration: 4.7s; animation-delay: 200ms; animation-fill-mode: forwards; } .article-paragraph { top: 24px; background: black; width: 0; height: 23px; padding: 0; float: right; z-index: 30; text-align: right; opacity: 0; } .article-paragraph.play { animation-name: movingpar; animation-delay: 400ms; animation-duration: 4.2s; animation-fill-mode: forwards; } /* keyframes 保持不变 */ @keyframes movingnum { 0%, 100% { width: 0px; } 10%, 90% { width: 31px; padding: 6.7px; opacity: 1; } } @keyframes movingpar { 0%, 100% { width: 0px; opacity: 0; } 10%, 90% { width: 300px; padding: 11px; opacity: 1; } }
步骤2:添加滑块切换监听代码
从你的HTML能看出用的是Swiper滑块,我们可以监听它的slideChange事件,在切换时重置.play类:
// 初始化Swiper(如果还没初始化) const swiper = new Swiper('.swiper-container', { // 这里填你的Swiper配置项 }); // 监听滑块切换事件 swiper.on('slideChange', function() { // 先移除所有元素的.play类 document.querySelectorAll('.article-num.play, .article-paragraph.play').forEach(el => { el.classList.remove('play'); }); // 强制浏览器重绘(关键!否则直接加类可能不触发动画) void document.body.offsetWidth; // 给当前激活的.slide下的元素添加.play类 const activeArticle = document.querySelector('.swiper-slide-active .article'); if (activeArticle) { activeArticle.querySelector('.article-num').classList.add('play'); activeArticle.querySelector('.article-paragraph').classList.add('play'); } });
方案二:纯CSS配合父元素.play类(仍需少量JS触发)
如果想尽量少用JS,可以通过父元素的.play类结合兄弟选择器触发动画,但还是需要JS来重置父元素的.play类:
修改后的CSS
/* 基础样式保持不变 */ .article.active { height: 75px; margin-top: -109px; margin-left: -70px; color: white; width: 100%; opacity: 0.8; z-index: 105; } .article-num { background: red; float: right; margin-top: 20px; width: 0; height: 32px; padding: 0; font-size: 27px; opacity: 0; } .article-paragraph { top: 24px; background: black; width: 0; height: 23px; padding: 0; float: right; z-index: 30; text-align: right; opacity: 0; } /* 当父滑块拥有.play类时,触发子元素动画 */ .swiper-slide.play .article.active .article-num { animation-name: movingnum; animation-duration: 4.7s; animation-delay: 200ms; animation-fill-mode: forwards; } .swiper-slide.play .article.active .article-paragraph { animation-name: movingpar; animation-delay: 400ms; animation-duration: 4.2s; animation-fill-mode: forwards; } /* keyframes 保持不变 */ @keyframes movingnum { 0%, 100% { width: 0px; } 10%, 90% { width: 31px; padding: 6.7px; opacity: 1; } } @keyframes movingpar { 0%, 100% { width: 0px; opacity: 0; } 10%, 90% { width: 300px; padding: 11px; opacity: 1; } }
对应的JS触发代码
同样监听Swiper切换事件,重置父元素的.play类:
const swiper = new Swiper('.swiper-container', { // 你的Swiper配置 }); swiper.on('slideChange', function() { // 移除所有滑块的.play类 document.querySelectorAll('.swiper-slide.play').forEach(el => { el.classList.remove('play'); }); // 强制浏览器重绘 void document.body.offsetWidth; // 给当前激活的滑块添加.play类 document.querySelector('.swiper-slide-active').classList.add('play'); });
为什么需要强制重绘?
浏览器会优化样式变化,如果直接移除再添加类,可能会被合并成一次样式更新,动画就不会重新触发。void document.body.offsetWidth会强制浏览器计算元素尺寸,触发重绘,这样后续的类添加就会被识别为新的样式变化,从而重新执行动画。
内容的提问来源于stack exchange,提问作者torresito
相关产品推荐
相关产品推荐

