CSS 过渡

过渡(transition)让属性值的变化不再是瞬间突变,而是在一段时间内平滑渐变。只写一行代码,就能给页面带来细腻的交互质感。

transition 四要素

过渡由四个属性控制:

css
.button {
  background: #2563eb;
  /* 简写:属性 时长 缓动 延迟 */
  transition: background 0.2s ease 0s;
}

.button:hover {
  background: #1d4ed8;
}

分写形式

css
.element {
  transition-property: background, transform;
  transition-duration: 0.3s, 0.2s;
  transition-timing-function: ease, ease-out;
  transition-delay: 0s, 0.1s;
}

transition-property — 哪些属性过渡

指定哪些 CSS 属性变化时触发过渡:

css
.box {
  transition-property: background;
  /* 仅背景色变化时有动画 */
}

.all {
  transition-property: all;
  /* 所有可过渡的属性都参与(默认值) */
}

使用 all 虽然方便,但会带来性能开销——浏览器需要监听元素的所有属性变化。建议明确指定需要过渡的属性名。

transition-duration — 持续时长

css
.slow { transition-duration: 1s; }      /* 1 秒 */
.normal { transition-duration: 200ms; } /* 200 毫秒 */
.fast { transition-duration: 0.15s; }   /* 150 毫秒 */

一般 UI 交互(hover、focus)建议在 150ms~300ms 之间。太慢会让界面感觉迟钝。

transition-timing-function — 缓动函数

控制动画速度曲线:

效果
ease慢→快→慢(默认,最常用)
linear匀速
ease-in慢→快
ease-out快→慢
ease-in-out慢→快→慢(比 ease 更平滑)
cubic-bezier(x1, y1, x2, y2)自定义贝塞尔曲线
css
.button {
  transition: transform 0.2s ease-out;
}
.button:hover {
  transform: scale(1.05);
}

自定义贝塞尔曲线

css
/* ease 的等价写法 */
transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);

/* 弹性效果 */
transition-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);

Chrome DevTools 的 Styles 面板中,点击缓动函数旁边的曲线图标可以可视化的编辑贝塞尔曲线。

transition-delay — 延迟

过渡开始前的等待时间:

css
.delayed {
  transition: opacity 0.3s ease 0.5s; /* 0.5s 后开始 */
}

/* 利用延迟实现依次出现 */
.item:nth-child(1) { transition-delay: 0s; }
.item:nth-child(2) { transition-delay: 0.1s; }
.item:nth-child(3) { transition-delay: 0.2s; }

哪些属性可以过渡

大部分数值型属性都可以过渡:

  • widthheightmax-width
  • marginpadding
  • backgroundborder-colorbox-shadow
  • opacity
  • transform(旋转、缩放、位移)
  • colorfont-size
  • filter(模糊、亮度等)

不可过渡的属性:displaypositionfont-familybackground-image: url(...)(图片切换无过渡)。

transition 简写

css
.element {
  /* 单个属性 */
  transition: opacity 0.3s ease;

  /* 多个属性用逗号分隔 */
  transition:
    background 0.2s ease,
    transform 0.2s ease,
    box-shadow 0.3s ease;
}

进场和退场的细节

过渡只在触发时生效,取消触发时也会反向过渡。但你可以为进场和退场设置不同的参数:

css
.button {
  background: #2563eb;
  /* 退场:慢一点 */
  transition: background 0.3s ease;
}

.button:hover {
  background: #1d4ed8;
  /* 进场:快一点 */
  transition: background 0.1s ease;
}

将 hover 状态的 transition 设为更短时长,可以让”进入动画”更快,而”离开动画”保持原有时长。这符合用户直觉——进场干净利落,退场柔和收尾。

性能注意事项

过渡期间浏览器需要重新计算样式、布局和绘制。不同属性的性能开销差异巨大:

开销属性
低(推荐)opacitytransform
colorbackground
高(避免)widthheightmarginleft/top
css
/* ✅ 推荐:用 transform 实现位移 */
.box {
  transition: transform 0.3s ease;
}
.box:hover {
  transform: translateY(-4px);
}

/* ❌ 避免:用 margin 实现位移 */
.box {
  transition: margin 0.3s ease;
}
.box:hover {
  margin-top: -4px;
}

transformopacity 的过渡只涉及合成(compositing),不需要重排(reflow)和重绘(repaint),性能远优于其他属性。

如果你需要比过渡更复杂的动画——比如多阶段、循环、播放控制等——请使用 CSS 动画(@keyframes + animation)。