如何让checkbox选中动画随每次勾选重启(仅用CSS+label+input)
问题背景
我有一个适配后的胶囊容器组件,点击容器后右侧会显示一个绿色小元素。组件用到两类样式属性:
transition:控制绿色容器的显示/隐藏过渡animation:控制绿色容器内"V"型图标的旋转效果
其中transition表现正常,每次点击都能触发绿色容器的显示/隐藏,但"V"图标的动画仅第一次点击时执行,后续点击无法重启。
当前问题
绿色容器内的"V"图标动画时长设为2秒,仅首次点击时完整执行,之后再点击容器,动画不再重新启动。
我的HTML结构:
<body> <div class="m__main"> <div class="m__plats" id="entrées"> <label> <article class="m__item"> <input type="checkbox" id="m__switch" value="1"> <div class="m__info "> <div class="m__texte"> <h3 class="m__titre">Ravioles de foie gras</h3> <p class="m__details">Accompagnés de leur crème à la truffe</p> </div> <p class="m__prix"> 25€</p> </div> <div class="m__selection"> <span class="material-icons check__icon">check_circle</span> </div> </article> </label> </div> </div> </body>
我通过checkbox+外层label实现了容器整体可点击,同时隐藏了原生input控件。
对应的SCSS代码:
#m__switch:checked{ ~.m__selection { opacity: 100%; width: 7rem; transition: transform 0.4s ease-in-out, width 0.4s ease-in-out, opacity 0.4s ease-in-out; } } .check__icon { animation: m__rotate 2s linear 3 ; }
尝试过用#m__switch:checked选择器直接控制.check__icon的动画,但完全无法触发,只能单独给图标设置动画属性,这就导致了动画无法随点击重启的问题。也试过用transition实现旋转效果,但视觉表现不理想。
需求说明
希望每次点击胶囊容器显示绿色元素时,"V"图标都能重新执行旋转动画。试过用radio控件替代checkbox,但无法实现取消选中后隐藏绿色容器的效果。
解决方案
CSS本身没有原生的"重启动画"API,但可以通过两种方式实现需求:
方法1:纯CSS状态切换重置动画
通过给未选中状态下的图标重置动画为none,选中时再重新应用动画规则,利用状态切换强制动画重启:
/* 未选中时重置动画状态 */ #m__switch:not(:checked) ~ .m__selection .check__icon { animation: none; } /* 选中时触发动画 */ #m__switch:checked ~ .m__selection .check__icon { animation: m__rotate 2s linear 3; animation-play-state: running; } /* 确保旋转关键帧已定义 */ @keyframes m__rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
原理是当checkbox从选中切换为未选中时,图标动画被重置为无状态,再次选中时会重新初始化并执行动画。
方法2:JavaScript强制重启动画
如果CSS方案在复杂场景下不生效,可以用JS监听checkbox状态变化,通过移除再重新添加动画类的方式触发重启:
首先修改SCSS,将动画逻辑放到独立类中:
.check__icon { animation: none; } .check__icon.rotate { animation: m__rotate 2s linear 3; } @keyframes m__rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
然后添加JS代码:
const checkbox = document.getElementById('m__switch'); const checkIcon = document.querySelector('.check__icon'); checkbox.addEventListener('change', function() { if (this.checked) { // 先移除动画类,触发DOM重绘 checkIcon.classList.remove('rotate'); // 等待重绘完成后再添加类,强制重启动画 requestAnimationFrame(() => { checkIcon.classList.add('rotate'); }); } else { checkIcon.classList.remove('rotate'); } });
这种方式兼容性更好,能确保每次选中容器时,动画都能重新执行。
内容的提问来源于stack exchange,提问作者Elradsoldier

