如何在CSS中实现鼠标悬停时减慢背景平移动画
解决背景平移动画hover时减速且保留状态的问题
你遇到的核心问题是:直接在hover时重写animation属性会导致动画从头开始播放,无法保持当前的滚动状态。那个视觉错觉的解决思路是用两个完全相同的动画元素层,一个以正常速度播放,一个以慢速播放,hover时切换显示,并同步两者的背景位置,让视觉上看起来是平滑减速而非重置动画。
修改后的完整代码
HTML
<div class="bg-container"> <div class="bg-fast"></div> <div class="bg-slow"></div> </div>
CSS
@keyframes backgroundScroll { 0% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } .bg-container { width: 30vw; height: 30vh; position: relative; overflow: hidden; } .bg-fast, .bg-slow { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: repeating-linear-gradient( 45deg, #EE0000, #EE0000 10px, #990000 10px, #990000 20px ); background-size: 150%; } .bg-fast { animation: backgroundScroll 3s linear infinite; } .bg-slow { animation: backgroundScroll 20s linear infinite; opacity: 0; pointer-events: none; /* 避免干扰hover事件 */ } .bg-container:hover .bg-fast { opacity: 0; pointer-events: none; } .bg-container:hover .bg-slow { opacity: 1; pointer-events: auto; }
JavaScript(关键:同步背景位置)
const container = document.querySelector('.bg-container'); const fastBg = document.querySelector('.bg-fast'); const slowBg = document.querySelector('.bg-slow'); // 获取当前背景位置的X值 function getBgPositionX(element) { const bgPos = window.getComputedStyle(element).backgroundPosition; return parseFloat(bgPos.split(' ')[0]); } // hover时同步位置 container.addEventListener('mouseenter', () => { const currentPos = getBgPositionX(fastBg); slowBg.style.backgroundPosition = `${currentPos}% 50%`; }); // 离开时同步位置 container.addEventListener('mouseleave', () => { const currentPos = getBgPositionX(slowBg); fastBg.style.backgroundPosition = `${currentPos}% 50%`; });
核心逻辑说明
- 双层结构:用容器包裹两个完全重叠的背景div,分别绑定快慢两种速度的动画,初始只显示快动画层。
- 位置同步:通过JS获取当前显示层的背景位置,在hover/离开时把该位置赋值给即将显示的层,确保动画状态连续。
- 视觉切换:通过
opacity控制层的显示隐藏,配合pointer-events避免事件干扰,让切换过程无感知。
这种方法本质是利用两个动画的视觉连续性,避免了直接修改animation属性导致的动画重置问题,完美实现了hover时平滑减速的效果。
内容的提问来源于stack exchange,提问作者henxdl
相关产品推荐
相关产品推荐

