如何实现第二次hover元素时触发与首次不同的CSS动画?
实现不同次数hover触发不同动画的方案
你当前的写法只能固定触发同一个动画,CSS本身没有原生的交互次数记录能力,可通过以下两种方案实现需求:
方案1:CSS + 少量JS(推荐,兼容性和扩展性更好)
首先补充两个动画的关键帧定义,区分初始状态和已hover过一次的状态的hover规则:
/* 自定义两款动画的关键帧,可根据需求修改 */ @keyframes myAnim { /* 首次hover动画示例 */ 0% { transform: scale(1); } 100% { transform: scale(1.5) rotate(360deg); } } @keyframes myAnim2 { /* 第二次及以后hover动画示例 */ 0% { transform: scale(1.5); } 100% { transform: scale(1) rotate(-360deg); } } /* 未触发过首次动画时,hover走第一个动画 */ .star:not(.hovered):hover { animation: myAnim 2s ease 0s 1 normal forwards; } /* 首次动画触发完成后,hover走第二个动画 */ .star.hovered:hover { animation: myAnim2 2s ease 0s 1 normal forwards; }
添加少量JS监听首次动画结束,给元素加标记类:
document.querySelectorAll('.star').forEach(star => { star.addEventListener('animationend', function(e) { // 仅首次myAnim动画结束时添加标记类,避免重复触发 if(e.animationName === 'myAnim' && !this.classList.contains('hovered')) { this.classList.add('hovered'); } }) })
方案2:纯CSS实现(无需引入JS,需调整DOM结构)
先调整元素结构,嵌套隐藏的checkbox作为状态标记:
<label class="star-wrap"> <input type="checkbox" class="star-state" hidden> <div class="star"></div> </label>
对应CSS规则:
/* 自定义两款动画的关键帧,可根据需求修改 */ @keyframes myAnim { 0% { transform: scale(1); } 100% { transform: scale(1.5) rotate(360deg); } } @keyframes myAnim2 { 0% { transform: scale(1.5); } 100% { transform: scale(1) rotate(-360deg); } } /* 未标记已hover时,首次hover触发第一个动画 */ .star-state:not(:checked) + .star:hover { animation: myAnim 2s ease 0s 1 normal forwards; pointer-events: none; } /* 已标记hover后,hover触发第二个动画 */ .star-state:checked + .star:hover { animation: myAnim2 2s ease 0s 1 normal forwards; } /* 首次动画播放完成后恢复元素交互,自动标记状态为已hover */ .star-state:not(:checked) + .star { animation: resetEvent 2s ease forwards; } @keyframes resetEvent { to { pointer-events: auto; } }
该方案无需JS,但需要调整DOM结构,扩展性弱于JS方案,适合无法引入脚本的场景。
内容的提问来源于stack exchange,提问作者Ralfs
相关产品推荐
相关产品推荐

