06过渡

transition 让样式变化不再瞬间跳变,而是平滑地滑过去。 你只声明「起点」和「终点」,中间的每一帧浏览器替你补——它是 CSS 动效里 性价比最高的一行代码

约 40 分钟 8 个动手实验 动效四要素

一、过渡的本质:状态 A 到状态 B 的补间

过渡是一种补间动画(tweening): 样式从旧值到新值变化时,浏览器自动生成中间帧。它不能自己发动, 必须由一次「状态变化」触发——hover 移入移出、聚焦失焦、类名增删、媒体查询命中,都算。

同一份 hover 样式:把 .smooth 的 transition 删掉,两枚按钮就都“瞬移”了
头号新手坑:transition 要写在基态(.btn)而不是触发态(.btn:hover)。 写在 hover 里,移入时有动画、移出时瞬间弹回——因为移出时 hover 规则连同 transition 一起失效了。

除 hover 外,一切「能让属性值变化」的场合都能触发过渡:

最实用的工程模式:CSS 管效果,JS 只负责加/删一个类名—— 职责分离,各干各的。第七节的抽屉就是纯 CSS 版本的同一思想。

二、transition-property 与 duration:动什么、动多久

过渡四要素的前两个:transition-property 决定哪些属性参与过渡transition-duration 决定花多久完成

transition-property 取值对比
property 取值含义建议
all(默认)所有可过渡属性都过渡省心,但重排属性会被一起拖进动画
具体属性名只有列出的属性过渡推荐:可控、性能好
none完全禁用过渡调试时临时关掉动效

duration 的单位必须写sms), 默认值是 0s——这就是「明明写了 transition 却没动画」的常见原因之一。 拖动感受一下时长差异:

悬停任意跑道,对比四档时长的升降——把 .d1 的 0.1s 改成 0.01s 感受“瞬移”
时长手感参考:按钮等小反馈 0.15~0.3s;卡片、面板 0.3~0.5s;全屏转场 0.5~0.8s。 超过 1s 的过渡,用户会觉得「卡了」。

三、transition-timing-function:速度曲线

同样 0.6 秒,怎么个跑法由速度曲线决定: 匀速、先快后慢、先慢后快、甚至冲过头再弹回来。

五条跑道五种跑法——注意第五条会冲过头弹回来;把 .t2 的 ease 改成 steps(4) 看熄格跳变
UI 惯例:入场用 ease-out(快进慢停,干脆利落), 出场用 ease-in(慢起快走,迅速让位)。回弹曲线只给「强调型」小元素用, 满屏回弹会显得廉价。

四、transition-delay 与简写:第四要素

transition-delay 是「等多久才出发」。单个元素用它不多, 一群元素排队出场时它就是节奏大师。

悬停整行,五个徽章错峰浮起——把 delay 步长 0.08s 改成 0.2s 让它们“排队得更明显”
简写 transition整体重置四个子属性—— 先写了子属性再写简写,前面的设置会被覆盖。同一个元素只用一种写法。

五、哪些属性值得过渡:性能分三档

不是所有属性过渡起来都一样轻快。按浏览器渲染成本分三档:

过渡性能三档:合成层 / 重绘 / 重排
档位代表属性渲染成本建议
合成层 ⭐⭐⭐transform / opacityGPU 直接算,不碰布局动画首选
重绘 ⭐⭐color / background / box-shadow重新画像素,不重排短动画无妨
重排 ⭐width / height / top / margin牵一发动全身,兄弟全重算尽量避免做动画
不可过渡display / position / font-family离散值,没有「中间帧」换 opacity 或 transform 实现
悬停三个盒子——前两个走 GPU 稳如老狗,第三个每帧重排布局(把 .c 的 width 换成 transform: scaleX(1.4) 对比顺滑度)
height: auto 无法过渡——起点没有具体数值,浏览器不知道从几开始补间。 经典解法:①用 max-height 给一个「比内容大的上限」(见第七节抽屉); ②现代方案用 grid-template-rows: 0fr → 1fr 过渡。

六、多属性分组:一个元素,各玩各的节奏

逗号分隔多组过渡,每组有自己的时长和曲线。 高级感的 hover 往往就是「快的先走、慢的垫后」:

悬停卡片——先快速浮起,颜色和影子慢慢跟上(把 transform .25s 改成 1s,节奏就乱了,试试)
transition: all 图省事,但所有属性被迫同一种节奏, 还会把意外的重排属性拖进动画。正式项目里,写清楚每一个属性名。

七、实战:纯 CSS 抽屉(点一下展开)

把本章知识串起来:复选框当开关、max-height 过渡高度、箭头同步旋转。 不写一行 JavaScript,点击标题就能展开收起——手风琴、FAQ 列表的原型。

点击标题栏,抽屉滑出(再点收起)——把 max-height: 200px 改成 2000px 观察「空跑」的违和感
JS 版本一模一样:把 :checked 换成 JS 切换的 .open 类名, 点击事件只干「加减类」这一件事,动画完全交给 CSS——这就是状态与表现分离

八、本章小结

过渡四要素总表(背下来,随手就能写):

过渡四要素一览
子属性管什么常用值
transition-property哪些属性动具体属性名(推荐)/ all / none
transition-duration动多久0.15s ~ 0.5s(必须带单位)
transition-timing-function怎么个变速法ease / ease-out / cubic-bezier() / steps()
transition-delay多久后出发0s,错峰入场才用
transition(简写)一行全包transform 0.3s ease 0.1s
  • 过渡 = 状态 A → 状态 B 的补间,必须由状态变化触发;写在基态而非 :hover 里
  • 简写两个时间的识别规则:第一个永远是 duration,第二个才是 delay
  • 性能三档:transform / opacity 走 GPU,颜色类走重绘,宽高边距走重排(尽量别动画)
  • height: auto 不可过渡——用 max-heightgrid-template-rows: 0fr/1fr 绕行
  • 多属性逗号分组、错开时长,才有「编舞感」;正式项目别偷懒写 all
  • 下一章的 animation 是它的完全体:多关键帧、能循环、自动播放
动手练习:①把第二节的 0.3s 改成 0.03s 和 3s,感受「太快看不见、太慢像死机」; ②给第五节第三个盒子的 width 过渡换成 transform: scaleX(1.4),对比顺滑度; ③把第七节抽屉的 max-height: 200px 改成 2000px,观察「空跑」的违和感。
无障碍礼仪:尊重系统的「减少动态效果」设置—— @media (prefers-reduced-motion: reduce) { * { transition-duration: 0.01s !important; } }, 让晕动症用户也能舒服地用你的页面。