07动画

过渡只有「起点 → 终点」两站;animation + @keyframes 给你完整导演权几站、每站长什么样、循环几次、要不要倒放,全听你的。 而且不需要触发——绑定即开演。

约 50 分钟 7 个动手实验 CSS 动效完全体

一、动画 vs 过渡:什么时候用哪个

两兄弟分工明确:过渡是「反馈」,动画是「演出」。 hover 时亮一下是反馈,用过渡;loading 转圈、入场演出是持续的行为,用动画。

transition 与 animation 对比
对比项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% 和 100% 写成一样的值,循环时才不会跳帧。

三、animation 八个子属性逐个看

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

最难理解的是 directionfill-mode,各用一个对照实验说清楚:

normal 跳上去再瞬移下来;alternate 跳上去又跳下来——把 .b 的 alternate 改成 reverse 看它只往下钻
两盒都延迟 1.2s 开演——右边(both)等待期就藏在首帧里,演完停在终点(把 1.2s 改成 4s 看得更清楚)
「入场动画只在第一次加载时闪一下,之后一切如常」—— 这说明你忘了 fill-mode。想让元素演完停在终点,加 forwards; 有 delay 又不想它等的时候裸奔出来,加 backwards;两个都要就 both

四、简写与多动画:一个元素,两套戏

简写顺序(不必背,记住两个时间的规则就行——第一个是 duration,第二个是 delay):

一枚徽章同时演两套戏——1.4s 浮动 + 2.8s 变色(把两套 duration 改成一样,层次就没了)
多动画若操作同一个属性(比如都改 transform),后面的赢——前者被覆盖。 想叠加就分家:一套管 transform,一套管 filteropacity

五、animation-play-state:会暂停的跑马灯

animation-play-state: paused 让动画原地冻结(不是回到起点), 配合 hover 就是「跑马灯悬停暂停」——用户想细看时它乖乖停下。

鼠标移到跑马灯上,滚动冻结在当前帧(移开继续)——把 7s 改成 3s 让它跑快点
跑马灯三件套:轨道 width: max-content + 内容复制两份 + 滚动距离 50%。 JS 轮播图的 CSS 版原理一模一样,只是把「滚动到头重置」换成了「永远差 50%」。

六、实战:三个经典 loading 动效

面试和项目里出现频率最高的三件套:转圈、弹跳点、脉冲波纹。 每一个都不超过十行 CSS。

三件套同台——把弹跳点第二个点的 delay 改成 0.4s 感受「节奏太散」
三个套路背后的通用思想:转圈 = 旋转一个「半成品」;错峰 = 同一动画不同 delay; 波纹 = 动伪元素不动本体。看懂套路,loading 动效可以自己编。

七、性能与动画礼仪

动画是 CSS 里最烧性能的部分,规矩也最多。核心一条: 只动 transform 和 opacity——它们走 GPU 合成,不触发重排重绘。

动画性能取舍
做法成本替代方案
transform / opacity / filter合成层,GPU—— 就该用它
width / top / margin每帧重排transform: scale() / translate()
box-shadow / background每帧重绘大面积发光用伪元素 + opacity
满屏 infinite 动画持续耗电视口外的暂停,或干脆删掉
will-change 是「预订 GPU 层」,不是加速器开关: 常驻滥用反而多占内存。只在确实卡顿时加,动画完删掉。
动画礼仪三问:它帮用户理解了什么?打断注意力了吗?关掉页面会不会更舒服? 答不上来的动画,删掉是最大的优化。

八、本章小结

animation 八属性速查(简写顺序即表格顺序):

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) 复刻一个「回弹小球」。