如何移除CSS类时避免触发fade-in动画?
问题根源
问题出在.splash *的动画规则是持久绑定的——每次元素的动画属性从none(no_transition类)恢复时,浏览器会重新触发fade-in动画,因为它会重新应用这个默认动画规则。
下面是几种可行的解决方案:
方案1:让fade-in仅在元素首次渲染时触发
通过给已完成淡入的元素添加标记类,阻止后续样式变化时重新触发动画:
修改CSS
/* 仅给未完成淡入的元素应用动画 */ .splash *:not(.fade-completed) { animation: fade-in 1s ease-in forwards; opacity: 1; } @keyframes fade-in { 0% { opacity: 0; } 100% { opacity: 1; } } /* 保留原有error动画样式 */ .error { animation: shake 0.4s ease-in-out; border-color: red; } @keyframes shake { 0% { transform: translateX(0); } 25% { transform: translateX(-5px); } 50% { transform: translateX(5px); } 75% { transform: translateX(-5px); } 100% { transform: translateX(0px); } }
修改JS
// 页面加载完成后,给所有splash子元素绑定动画结束事件 document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('.splash *').forEach(el => { el.addEventListener('animationend', (e) => { // 仅监听fade-in动画结束事件 if (e.animationName === 'fade-in') { el.classList.add('fade-completed'); } }, { once: true }); // 事件仅触发一次 }); }); // 简化err函数,移除no_transition相关逻辑 function err(elem, msg) { if (msg) alert(msg); elem.classList.add('error'); elem.disabled = true; setTimeout(() => { elem.classList.remove('error'); elem.disabled = false; }, 1000); }
方案2:通过强制重绘避免触发默认动画
利用浏览器重绘机制,在移除no_transition前手动锁定动画状态:
修改CSS
.splash * { animation: fade-in 1s ease-in; opacity: 1; } @keyframes fade-in { 0% { opacity: 0; } 100% { opacity: 1; } } .error { animation: shake 0.4s ease-in-out forwards; border-color: red; } @keyframes shake { 0% { transform: translateX(0); } 25% { transform: translateX(-5px); } 50% { transform: translateX(5px); } 75% { transform: translateX(-5px); } 100% { transform: translateX(0px); } } .no_transition { animation: none !important; transition: none !important; }
修改JS
function err(elem, msg) { if (msg) alert(msg); elem.classList.add('error'); elem.disabled = true; setTimeout(() => { elem.classList.add('no_transition'); elem.classList.remove('error'); elem.disabled = false; // 手动设置动画为none,强制浏览器重绘 elem.style.animation = 'none'; void elem.offsetWidth; // 触发重绘 // 移除no_transition类,此时不会触发fade-in elem.classList.remove('no_transition'); // 恢复默认样式(可选) elem.style.removeProperty('animation'); }, 1000); }
方案3:用animation-play-state控制动画
通过暂停已完成的淡入动画,避免后续触发:
修改CSS
.splash * { animation: fade-in 1s ease-in forwards; opacity: 1; animation-play-state: running; } @keyframes fade-in { 0% { opacity: 0; } 100% { opacity: 1; } } .error { animation: shake 0.4s ease-in-out; border-color: red; animation-play-state: running !important; } @keyframes shake { 0% { transform: translateX(0); } 25% { transform: translateX(-5px); } 50% { transform: translateX(5px); } 75% { transform: translateX(-5px); } 100% { transform: translateX(0px); } }
修改JS
document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('.splash *').forEach(el => { el.addEventListener('animationend', (e) => { if (e.animationName === 'fade-in') { // 淡入完成后暂停动画,阻止后续触发 el.style.animationPlayState = 'paused'; } }, { once: true }); }); }); function err(elem, msg) { if (msg) alert(msg); elem.classList.add('error'); elem.disabled = true; setTimeout(() => { elem.classList.remove('error'); elem.disabled = false; }, 1000); }
内容的提问来源于stack exchange,提问作者Blue Herring
相关产品推荐
相关产品推荐

