如何实现hover时跑马灯平滑减速且避免transform元素偏移
问题根因
- 移位核心诱因是hover状态下添加的
transform-origin: top right:跑马灯动画全程用translateX做水平位移,默认变换原点是元素中心位置,hover时突然切换原点到右上角,浏览器会立刻基于新原点重新计算当前transform的渲染坐标,直接触发位置跳变。 - 重复声明的transition规则存在逻辑冲突:hover块内先后写了三次transition,最后一条
transition: transform 500ms ease-in-out 25ms会覆盖前面的配置,且transform属性正被关键帧动画持续驱动更新,给transform额外加过渡会和动画帧计算冲突,进一步加剧移位问题。 - 直接修改CSS变量
--animationTiming无法触发光滑的动画速率变化:关键帧动画不会对animation-duration的变量变化做自动补间,且原代码只放了一组内容,滚动到-50%位置时会出现空白断层,无法实现无缝效果。
修复后完整代码
HTML部分
<div class="wrapper"> <div class="track"> <div class="content"> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <!-- 追加第二组相同内容,实现无缝滚动衔接 --> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> </div> </div> </div>
SCSS部分
<style lang="scss"> :root { --marquee-speed-normal: 100s; --marquee-speed-hover: 300s; // 数值越大滚动越慢,按需调整 } .wrapper { position: relative; width: 100vw; max-width: 100%; height: 200px; overflow: hidden; } .track { position: absolute; white-space: nowrap; will-change: transform; // 仅给动画时长加过渡,实现平滑加减速,不要给transform加过渡避免和关键帧冲突 transition: animation-duration 3s cubic-bezier(0.47, 0, 0.745, 0.715); animation: marquee var(--marquee-speed-normal) linear infinite; &:hover { animation-duration: var(--marquee-speed-hover); } } @keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } } .content { display: flex; } .box { width: 500px; height: 200px; // 和容器高度匹配,避免不必要溢出 background-color: red; border: 1px solid #000; flex-shrink: 0; // 防止flex布局下盒子被压缩 } </style>
修复说明
- 全程移除
transform-origin自定义配置,保持默认变换原点,从根源消除原点切换导致的位置跳变 - 去掉冲突的transform过渡规则,仅对
animation-duration属性加过渡,既不会打断关键帧的滚动逻辑,还能实现速率变化的平滑补间 - 追加第二组重复内容,配合
translateX(-50%)的动画终点实现无缝循环滚动,不会出现空白断层 - 给box添加
flex-shrink: 0避免flex布局下元素被压缩,调整box高度和容器匹配,消除多余溢出。
内容的提问来源于stack exchange,提问作者fable
相关产品推荐
相关产品推荐

