CSS3 动画(animation):如何实现旋转/淡入等简单动画?
面试速答(30 秒版 TL;DR)
- CSS3 动画核心是两件事:用
@keyframes定义关键帧,用animation(或其拆分属性)把关键帧“挂”到元素上。 - 旋转加载最常见写法:
transform: rotate(...)+animation: spin 1s linear infinite;,并根据需要设置transform-origin。 - 动画要顺滑:尽量只动画
transform/opacity(更可能走合成层),少动left/top/width/height这类容易触发布局的属性。 animationvstransition:transition依赖状态变化(如:hover)且通常只有起止两态;animation可多关键帧、可循环、可独立播放。
心智模型:@keyframes 负责“时间轴”,animation 负责“播放参数”
可以把 CSS 动画理解成“把一个时间函数作用到样式上”:
@keyframes:描述 0% 到 100% 的过程中,哪些属性怎么变化。animation-*:描述 播放(多久、延迟、速度曲线、循环次数、方向、结束后停在哪一帧等)。
最小可用:实现一个旋转动画(spinner)
HTML:
<div class="spinner" aria-label="loading"></div>
CSS:
.spinner {
width: 24px;
height: 24px;
border: 3px solid #ddd;
border-top-color: #333;
border-radius: 50%;
/* 性能友好:只动画 transform */
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
面试补充点:
- 旋转动画通常用
linear,避免ease带来的“忽快忽慢”。 - 如果你需要绕某个点转:用
transform-origin: left center;等调整旋转中心。
再给两个高频例子:淡入与“弹一下”
1)淡入(入场)
.fade-in {
animation: fadeIn 200ms ease-out both;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(6px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
要点:
both等价于animation-fill-mode: both:开始前应用 0% 帧,结束后保留 100% 帧(常用于入场动画)。opacity + transform一般比改top/left更顺滑。
2)“弹一下”(强调反馈)
.pop {
animation: pop 240ms cubic-bezier(0.2, 0.9, 0.2, 1);
}
@keyframes pop {
0% {
transform: scale(0.96);
}
60% {
transform: scale(1.04);
}
100% {
transform: scale(1);
}
}
animation 常用参数速记(能口述)
animation 简写常见形态:
/* name duration timing-function delay iteration-count direction fill-mode */
.box {
animation: spin 1s linear 0s infinite normal both;
}
拆分属性(面试常问你是否知道有哪些):
animation-name:关键帧名字(对应@keyframes)。animation-duration:持续时间,默认是0s(这是“动画不播放”的常见原因)。animation-timing-function:速度曲线,常见linear/ease/ease-in/ease-out,也可用cubic-bezier(...)、steps(n, ...)。animation-delay:延迟多久开始。animation-iteration-count:播放次数,infinite表示无限循环。animation-direction:方向,常用normal/alternate(来回播放)。animation-fill-mode:结束后停在哪一帧,常用forwards/both。animation-play-state:running/paused,用于暂停/继续。
高频追问:怎么让动画更流畅?会不会触发重排?
面试答法建议“先结论,再展开”:
- 结论:优先动画
transform/opacity,尽量避免动画layout属性(如width/height/left/top)。 - 原因:
transform/opacity更可能只走合成(composite),不需要每帧做布局与重绘;而布局相关属性可能触发 重排/重绘。 - 实战技巧(点到为止):
- 需要提前提示浏览器:
will-change: transform;(用完及时移除,别滥用)。 - 对“转圈圈”这种长期动画,注意节能与可访问性,必要时降级。
- 需要提前提示浏览器:
易错点/坑(面试里很好加分)
- 忘了写
animation-duration:默认0s,看起来像没生效。 - 同一元素上多个地方都在写
transform:transform是一个整体属性,后写的会覆盖先写的。需要叠加时:- 合并成一个
transform: translate(...) rotate(...);或 - 用嵌套元素(外层负责平移,内层负责旋转);或
- 用 CSS 变量组合(进阶)。
- 合并成一个
display: none无法做过渡/动画:入场/退场更常见做法是opacity/transform配合visibility/pointer-events。- 忽略“减少动态效果”偏好:可以用媒体查询尊重用户设置。
@media (prefers-reduced-motion: reduce) {
.spinner,
.fade-in,
.pop {
animation: none !important;
}
}
速记要点(可背诵)
- CSS 动画 =
@keyframes(时间轴) +animation(播放参数)。 - 旋转 =
transform: rotate+linear+infinite。 - 性能优先动画
transform/opacity,少动画left/top/width/height。 duration默认0s;fill-mode: forwards/both决定“播完停哪”。