You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免div取消悬停时缩放动画出现卡顿或突兀效果?

解决Div悬停/取消悬停时的动画跳变问题

你的代码核心问题是混用了transition和animation,且hover状态直接设置静态scale值,导致鼠标移入/移出时,元素会先跳转到静态值再执行动画,破坏流畅性。此外初始的shrink动画未定义0%关键帧,也会导致初始状态衔接异常。

下面给出两种可行的解决方案:


方案一:纯CSS优化版

通过调整关键帧的起始/结束状态,移除冲突的transition和静态scale设置,让动画直接衔接元素的当前状态:

* {
  box-sizing: border-box;
  margin: 0;
}

body {
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container {
  margin: 10px;
  height: 60vh;
  width: 70vw;
  background-color: antiquewhite;
  /* 初始状态由shrink动画的forwards保持 */
  animation: shrink 0.45s ease-in-out 1 forwards;
}

.container:hover {
  /* 覆盖原有动画,播放弹跳放大动画并保持最终状态 */
  animation: stretch 1.5s ease-in-out 1 forwards;
}

@keyframes stretch {
  0% { scale: 0.7; } /* 匹配初始缩放状态 */
  20% { scale: 1; }
  40% { scale: 0.9; }
  60% { scale: 1; }
  80% { scale: 0.95; }
  100% { scale: 1; }
}

@keyframes shrink {
  0% { scale: 1; } /* 匹配hover后的最终状态 */
  20% { scale: 0.9; }
  100% { scale: 0.7; }
}

注意:如果鼠标在弹跳动画未结束时快速移出,此方案仍会有轻微跳变(因为CSS无法实时获取元素当前缩放值),如果需要完全无缝衔接,推荐方案二。


方案二:JavaScript辅助版

通过JS实时获取元素当前的缩放比例,动态设置动画的起始值,实现完全流畅的衔接:

CSS代码

* {
  box-sizing: border-box;
  margin: 0;
}

body {
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
}

.container {
  margin: 10px;
  height: 60vh;
  width: 70vw;
  background-color: antiquewhite;
  transform: scale(0.7); /* 初始缩放状态 */
}

/* 使用CSS变量定义动画的起始缩放值 */
@keyframes stretch {
  0% { transform: scale(var(--start-scale)); }
  20% { transform: scale(1); }
  40% { transform: scale(0.9); }
  60% { transform: scale(1); }
  80% { transform: scale(0.95); }
  100% { transform: scale(1); }
}

@keyframes shrink {
  0% { transform: scale(var(--start-scale)); }
  20% { transform: scale(0.9); }
  100% { transform: scale(0.7); }
}

/* 动画触发类 */
.bounce-in {
  animation: stretch 1.5s ease-in-out 1 forwards;
}

.bounce-out {
  animation: shrink 0.45s ease-in-out 1 forwards;
}

JavaScript代码

const container = document.querySelector('.container');

// 获取元素当前的缩放比例
function getCurrentScale(element) {
  const transform = window.getComputedStyle(element).transform;
  if (transform === 'none') return 1;
  const matrix = new DOMMatrix(transform);
  return matrix.a; // 等比缩放时,x/y轴缩放值一致
}

// 鼠标移入触发弹跳放大
container.addEventListener('mouseenter', () => {
  container.classList.remove('bounce-out');
  container.style.setProperty('--start-scale', getCurrentScale(container));
  container.classList.add('bounce-in');
});

// 鼠标移出触发弹跳缩小
container.addEventListener('mouseleave', () => {
  container.classList.remove('bounce-in');
  container.style.setProperty('--start-scale', getCurrentScale(container));
  container.classList.add('bounce-out');
});

// 动画结束后清除类,避免重复触发冲突
container.addEventListener('animationend', () => {
  container.classList.remove('bounce-in', 'bounce-out');
});

此方案无论鼠标何时移入/移出,动画都会从元素当前的缩放状态开始,完全消除跳变问题。


内容的提问来源于stack exchange,提问作者Aryan Srivastava

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 02:14:55