2、CSS过渡动画:transition属性详解、触发条件、贝塞尔曲线调优

大家好,我是你们的老朋友。今天我们来聊聊 CSS 过渡动画,也就是 transition 属性。

说实话,CSS 过渡是我在移动端开发中用得最多的动画方案。为什么?因为它简单、高效,而且浏览器对它的优化做得非常好。你不需要引入任何第三方库,几行代码就能让页面“活”起来。

2.1 transition 属性详解

先来看一个最基础的例子。假设你有一个按钮,希望鼠标悬停时背景色渐变:

.btn {
  background-color: #4CAF50;
  transition: background-color 0.3s ease;
}

.btn:hover {
  background-color: #45a049;
}

这段代码里,transition 是一个简写属性。它背后其实包含了四个子属性:

子属性 说明 示例值
transition-property 指定哪些属性需要过渡 allopacitytransform
transition-duration 过渡持续的时间 0.3s500ms
transition-timing-function 速度曲线(缓动函数) easelinearcubic-bezier()
transition-delay 延迟多久后开始过渡 0s0.1s

我个人习惯把 transition 拆开来写,这样可读性更好:

.btn {
  transition-property: background-color;
  transition-duration: 0.3s;
  transition-timing-function: ease;
  transition-delay: 0s;
}
小技巧: 如果你想让多个属性同时过渡,可以用逗号分隔。比如 transition: opacity 0.3s ease, transform 0.5s ease-out;。但要注意,每个属性的持续时间和缓动函数可以不同。

2.2 触发条件

过渡动画不会凭空发生。它需要一个“触发器”。说白了,就是元素的某个属性值发生了变化。

常见的触发条件有这些:

  • 伪类触发: :hover:focus:active:checked
  • JavaScript 动态修改: 通过 JS 改变元素的 style 属性或添加/移除 class
  • 媒体查询变化: 比如屏幕宽度改变时,元素的尺寸或布局发生变化
  • 元素状态变化: 比如 :disabled:enabled

嗯,这里要注意一点:不是所有 CSS 属性都能过渡。比如 display 就不行。为什么?因为 display 是离散的,它没有中间状态。你想想看,一个元素要么显示要么隐藏,不存在“半显示”的状态。

我在项目中遇到过一个问题:想做一个元素从隐藏到显示的淡入效果。一开始我写了 display: none → display: block 配合 opacity 过渡,结果发现完全不生效。后来才意识到,display 变化是瞬间的,浏览器不会给它做过渡。

避坑指南: 我曾经在移动端用 height: 0 → height: auto 做展开动画,结果发现过渡无效。因为 auto 是一个计算值,浏览器无法插值。正确的做法是用 max-height 来模拟,或者直接用 transform: scaleY()

2.3 贝塞尔曲线调优

接下来聊聊贝塞尔曲线。这是 transition-timing-function 的核心。

标准预设值有五个:easelinearease-inease-outease-in-out。但说实话,在移动端开发中,这些预设值往往不够用。你需要自定义贝塞尔曲线。

自定义的语法是 cubic-bezier(x1, y1, x2, y2)。四个参数控制着曲线的形状:

  • x1, y1: 第一个控制点的坐标
  • x2, y2: 第二个控制点的坐标

举个例子,我想做一个“回弹”效果:

.card {
  transform: scale(1);
  transition: transform 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55);
}

.card:active {
  transform: scale(0.95);
}

这个曲线会让元素先缩小,然后略微“过冲”再回弹到目标位置。看起来很有弹性,很自然。

我个人习惯在调试贝塞尔曲线时,用 Chrome DevTools 的“动画”面板。你可以实时拖动控制点,看到曲线变化对动画的影响。这比凭空想象要高效得多。

移动端调优建议:
  • 避免使用 ease-in 作为入场动画,因为它结束时会突然停止,显得很生硬
  • 入场动画推荐 ease-out 或自定义的缓出曲线
  • 出场动画推荐 ease-in,让元素“加速离开”
  • 回弹效果用 cubic-bezier(0.68, -0.55, 0.27, 1.55) 这类带负值的曲线

你想想看,为什么移动端特别强调缓动函数?因为手机屏幕小,用户对动画的细腻程度要求更高。一个生硬的动画会让人觉得“卡顿”,哪怕帧率是满的。

2.4 实战中的注意事项

最后,分享几个我在实战中总结的经验:

  • 性能优先: 尽量只对 opacitytransform 做过渡。这两个属性不会触发重排(reflow),性能最好。
  • 避免过渡所有属性: 不要用 transition: all 0.3s。这会监听所有属性的变化,性能开销大,而且容易引发意料之外的动画。
  • 合理使用延迟: transition-delay 可以用来做“错峰”动画。比如列表项依次出现,每个项延迟 0.1s。
  • 注意移动端点击穿透: 如果你用 opacity: 0 隐藏元素,记得加上 pointer-events: none,否则用户还是能点到它。

好了,关于 CSS 过渡动画,今天就聊到这里。下一节我们会深入 animation 属性,那才是真正的大招。记得动手试试上面的代码,光看是学不会的。