07动画
过渡只有「起点 → 终点」两站;animation + @keyframes
给你完整导演权:几站、每站长什么样、循环几次、要不要倒放,全听你的。
而且不需要触发——绑定即开演。
一、动画 vs 过渡:什么时候用哪个
两兄弟分工明确:过渡是「反馈」,动画是「演出」。 hover 时亮一下是反馈,用过渡;loading 转圈、入场演出是持续的行为,用动画。
| 对比项 | transition 过渡 | animation 动画 |
|---|---|---|
| 触发方式 | 状态变化(hover / 类名) | 自动播放,绑定即跑 |
| 关键帧数 | 只有首尾两帧 | 任意多帧(0%~100% 随便加) |
| 循环 | 不可循环 | infinite 随意 |
| 倒放 / 往返 | 状态回去就自动「倒放」 | direction 手动控制 |
| 结束定格 | 自然回到基态 | fill-mode 可停在终点 |
| 典型场景 | hover 反馈、展开收起 | loading、入场、氛围动效 |
.vs-badge 的 duration 从 1.6s 改成 4s 看它"懒洋洋"二、@keyframes:动画的分镜表
动画分两步:先定义关键帧,再绑到元素上。
关键帧就是分镜表——from/to 只是最简形式(等价于 0%/100%),
中间的百分比站点随便加,站点越多动作越细腻。
50% 的 scale 改成 1.5、把 100% 的 translateX 改成 276px 看循环跳帧0% → 25% → 50% → 75% → 100%:五站分镜,infinite 无缝循环
三、animation 八个子属性逐个看
animation 是一个八合一简写,拆开每个都能单独写:
| 子属性 | 管什么 | 常用值 |
|---|---|---|
animation-name | 用哪套关键帧 | 对应 @keyframes 的名字 |
animation-duration | 一轮多久 | 0.3s ~ 4s |
animation-timing-function | 每两站之间怎么跑 | 与过渡相同:ease / linear / cubic-bezier() |
animation-delay | 多久后开演 | 错峰入场、延迟出场用 |
animation-iteration-count | 演几轮 | infinite / 数字 |
animation-direction | 方向 | normal / alternate(往返)/ reverse |
animation-fill-mode | 开演前 / 结束后定格在哪 | none / forwards / backwards / both |
animation-play-state | 播放 / 暂停 | running / paused |
最难理解的是 direction 和 fill-mode,各用一个对照实验说清楚:
.b 的 alternate 改成 reverse 看它只往下钻演完弹回
停在终点
forwards;
有 delay 又不想它等的时候裸奔出来,加 backwards;两个都要就 both。四、简写与多动画:一个元素,两套戏
简写顺序(不必背,记住两个时间的规则就行——第一个是 duration,第二个是 delay):
两套动画互不干扰:transform 管位置,filter 管颜色
transform,一套管 filter 或 opacity。五、animation-play-state:会暂停的跑马灯
animation-play-state: paused 让动画原地冻结(不是回到起点),
配合 hover 就是「跑马灯悬停暂停」——用户想细看时它乖乖停下。
轨道内容复制了两份,滚过一半时正好首尾衔接 —— 无缝循环的秘密
width: max-content + 内容复制两份 + 滚动距离 50%。
JS 轮播图的 CSS 版原理一模一样,只是把「滚动到头重置」换成了「永远差 50%」。六、实战:三个经典 loading 动效
面试和项目里出现频率最高的三件套:转圈、弹跳点、脉冲波纹。 每一个都不超过十行 CSS。
七、性能与动画礼仪
动画是 CSS 里最烧性能的部分,规矩也最多。核心一条: 只动 transform 和 opacity——它们走 GPU 合成,不触发重排重绘。
| 做法 | 成本 | 替代方案 |
|---|---|---|
动 transform / opacity / filter | 合成层,GPU | —— 就该用它 |
动 width / top / margin | 每帧重排 | transform: scale() / translate() |
动 box-shadow / background | 每帧重绘 | 大面积发光用伪元素 + opacity |
满屏 infinite 动画 | 持续耗电 | 视口外的暂停,或干脆删掉 |
will-change 是「预订 GPU 层」,不是加速器开关:
常驻滥用反而多占内存。只在确实卡顿时加,动画完删掉。八、本章小结
animation 八属性速查(简写顺序即表格顺序):
| 属性 | 一句话 | 高频值 |
|---|---|---|
animation-name | 用哪套分镜 | @keyframes 名 |
animation-duration | 一轮多久 | 0.3s ~ 4s |
animation-timing-function | 站间怎么跑 | ease / linear / cubic-bezier() |
animation-delay | 多久开演 | 错峰用 0.1s 级 |
animation-iteration-count | 演几轮 | infinite / 1 |
animation-direction | 方向 | alternate 往返 |
animation-fill-mode | 前后定格 | forwards / both |
animation-play-state | 播放暂停 | paused 悬停冻结 |
- 动画 = @keyframes 分镜 + animation 绑定,自动播放,与过渡的「状态触发」本质不同
- 百分比站点随便加,0% 和 100% 写成一样才能无缝循环
- 简写两个时间的规则与过渡相同:第一个是 duration,第二个是 delay
alternate做真往返;fill-mode: both让延迟期藏首帧、结束停末帧- 多动画逗号分隔,同属性后者覆盖前者——想让它们叠加就分属性写
- 性能铁律:只动 transform / opacity / filter;loading 三件套都是它们的变体
10% { opacity: 0.4; } 站点,看闪烁效果;
②把第六节弹跳点的 delay 间隔改成 0.4s,感受「节奏太散」;
③给跑马灯加 animation-direction: reverse,让它反着滚。
最后用 alternate + cubic-bezier(0.34, 1.56, 0.64, 1) 复刻一个「回弹小球」。