如何实现 div 悬停缩放时的平滑双向动画(无抖动)

5次阅读

如何实现 div 悬停缩放时的平滑双向动画(无抖动)

本文详解如何通过 CSS 自定义属性(CSS Variables)与 transition 配合 @keyframes,消除 hover/unhover 动画中常见的“跳变”现象,实现真正流畅、可逆的缩放过渡效果。

本文详解如何通过 css 自定义属性(css variables)与 `transition` 配合 `@keyframes`,消除 hover/unhover 动画中常见的“跳变”现象,实现真正流畅、可逆的缩放过渡效果。

在 CSS 动画实践中,一个常见痛点是:当使用 hover 触发 scale 变化时,若同时为常态和悬停态分别定义了 animation(如 shrink 和 stretch),浏览器往往无法自动衔接动画状态——导致 unhover 时元素先“瞬移”回初始 scale 值,再执行退出动画,产生明显抖动或卡顿。

根本原因在于:CSS animation 是单向声明式过程,不具备状态记忆能力;而 transition 虽天然支持双向过渡,但无法直接驱动复杂关键帧序列(如弹性缓动、多段缩放)。原方案混合使用 animation 与 transition,且未同步起始 / 结束状态,造成动画上下文断裂。

✅ 正确解法是: 用 CSS 自定义属性(–val)作为“状态桥接器”,将悬停动画的最终 scale 值实时传递给常态样式,并让 transition 承担主过渡职责,animation 仅用于增强悬停进入的视觉表现

以下是优化后的专业级实现:

* {box-sizing: border-box;   margin: 0;}  body {height: 100vh;   width: 100vw;   display: flex;   justify-content: center;   align-items: center;}  .container {/* 核心:启用 scale 的 transition,且初始值与动画起点一致 */   transition: scale 0.45s ease-in-out;   margin: 10px;   height: 60vh;   width: 70vw;   background-color: antiquewhite;   /* 初始 scale 设为 0.7,同时初始化 --val 为相同值 */   scale: 0.7;   --val: 0.7;}  .container:hover {/* hover 时仅触发动画,不直接设 scale —— 由 animation 内部控制 */   animation: stretch 1.5s ease-in-out 1 forwards;}  @keyframes stretch {0% {     scale: var(--val); /* 从当前 --val 值开始(即上一帧结束值)*/   }   20% {scale: 1; --val: 1;}   40% {scale: 0.9; --val: 0.9;}   60% {scale: 1; --val: 1;}   80% {scale: 0.95; --val: 0.95;}   100% {scale: 1; --val: 1;} }

? 关键设计说明:

  • –val 在 @keyframes 中持续更新,始终记录当前动画结束时的 scale 值;
  • .container 的 transition: scale … 确保 unhover 时能以该 –val 值为起点,平滑过渡回 scale: 0.7;
  • 移除了冗余的 shrink 动画——它已被 transition 完全替代,更轻量、更可控;
  • forwards 保证动画结束后样式保持在 100% 状态,使 –val: 1 生效,为退出过渡提供正确起点。

⚠️ 注意事项:

  • 自定义属性需在 :root 或元素自身作用域内声明,此处直接在 .container 上定义并更新,确保作用域隔离;
  • 不要对同一属性(如 scale)同时施加 transition 和 animation,否则行为不可预测;本方案严格分工:animation 负责 hover 进入的精细节奏,transition 负责 unhover 退出的自然衰减;
  • 若需支持旧版浏览器(如 IE),应添加 -webkit-transform: scale() 回退,并避免使用 scale 简写(改用 transform: scale())。

总结:平滑双向缩放的本质,是让进出动画共享可追踪的状态。CSS 变量为此提供了优雅的桥梁,配合语义清晰的 transition 控制,无需 JavaScript 或第三方库,即可达成专业级交互动效。

text=ZqhQzanResources