transition适用于用户触发的起始态到结束态交互,如按钮悬停缩放、菜单展开、输入框聚焦变色、卡片上浮;animation必须用于循环、多阶段、自动播放、暂停或倒放的动效,如无限旋转加载图标、打字效果、页面打开即执行的淡入动画。

直接结论:用户触发的「起始态 → 结束态」交互(比如悬停、点击、聚焦),用 transition;需要循环、多阶段、自动播放、暂停或倒放的动效,必须用 @keyframes + animation。
transition 适合哪些交互场景
它只响应属性值的显式变更,且必须有两个可计算的明确状态。不是所有“看起来在动”的地方都该用它。
- 按钮悬停时
transform: scale(1)→scale(1.05),同时background-color变深 - 导航菜单展开时用
max-height或opacity+transform过渡(不能用height: auto) - 输入框获得焦点时,
border-color和box-shadow同时变化 - 卡片 hover 上浮:
transform: translateY(0)→translateY(-4px)
常见失效原因:transition: all 0.3s 写了但没效果,大概率是漏写了起始态(比如默认没设 transform: scale(1)),或改了不支持过渡的属性(如 display、height: auto、left)。
animation 必须用在哪些地方
transition 没有时间轴概念,无法定义中间帧、循环次数或播放控制。一旦需求里出现以下任意一条,就得切到 @keyframes:
- 加载图标要无限旋转:
animation-iteration-count: infinite - “打字效果”需逐字出现,或“心跳脉冲”要
animation-direction: alternate - 页面一打开就执行淡入,不等用户操作(
animation-delay可控,但无需触发源) - 动画中途要暂停(
animation-play-state: paused)或由 JS 动态控制进度
典型翻车点:用 animation 做 hover 弹出菜单,忘了加 animation-fill-mode: forwards,结果动画一结束立刻回退到初始态,UI 断层;或者只写 @keyframes slideIn { to { transform: translateX(100px); } },漏了 from 或 0%,浏览器没法推断起始值,动画不动。
同一属性上混用 transition 和 animation 的风险
浏览器不会叠加两者,而是按声明顺序覆盖——后声明的生效,前一个被忽略。例如:
.box {
transition: transform 0.3s;
animation: slideIn 2s;
}
@keyframes slideIn {
to { transform: translateX(100px); }
}
这段代码中,transform 的过渡完全被 animation 接管,transition 形同虚设。
安全做法是分层使用:
- 让
transition管交互态(比如 hover 时缩放、点击时阴影) - 让
animation管独立节奏的视觉反馈(比如图标旋转 + 发光) - 若必须共存,确保作用于不同属性:例如
transition控opacity,animation控transform
JS 控制动效时该选哪个
别在 JS 里反复写 el.style.transition = 'opacity 0.2s' 再改 el.style.opacity——极易因渲染时机冲突导致不触发或跳帧。
更稳的路径是:
- 用 class 切换驱动
transition(el.classList.add('is-active')) - 复杂控制(如拖拽中实时更新位置)优先用
element.animate()(Web Animations API),它支持暂停、重设时间、设置当前进度 - 避免用 JS 手动轮询修改
style触发transition,尤其是高频操作场景
真正容易被忽略的是:动画中修改 transform 不会打断 animation,但改 transition-duration 会重置整个过渡流程——这种隐式重置在调试时极难定位。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











