第23课:变换与过渡
CSS 提供了两种在不借助 JavaScript 的情况下改变元素外观的机制:变换(Transform) 和 过渡(Transition)。变换通过修改元素的坐标空间实现平移、旋转、缩放和倾斜,且不占据布局空间、不触发回流;过渡则让属性值的变化变得平滑,赋予界面细腻的交互感。两者结合,足以构建流畅的交互动效。本节课将逐层解析 transform 的 2D 与 3D 函数、transition 的精细控制,以及贝塞尔曲线背后的时间函数原理。
1. transform 变换:在不破坏布局的情况下改变元素形态
transform 属性对元素应用矩阵变换,修改其视觉呈现,但不改变元素在文档流中的布局空间。其他元素仍按变换前的位置排列,不会因变换而重新布局。
1 | .box { |
1.1 为什么变换不触发回流?
浏览器的渲染流水线大致为:布局(Layout)→ 绘制(Paint)→ 合成(Composite)。transform 发生在合成阶段,仅操作 GPU 上的图层纹理,不会触发前面的布局和绘制步骤。这也是 transform 在动画中性能优于 top/left 等属性的根本原因。
1.2 2D 变换函数
平移:translate()
将元素沿 X 轴和 Y 轴移动。
1 | /* 向右 50px,向下 30px */ |
百分比参照:translate() 使用百分比时,参照的是元素自身的尺寸(而非父容器)。这是实现绝对居中定位的关键。
1 | /* 经典:绝对定位元素完美居中 */ |
旋转:rotate()
将元素绕指定点旋转。2D 旋转默认绕元素的中心点(可通过 transform-origin 修改)。
1 | /* 顺时针旋转 45 度 */ |
常用角度单位:
deg(度):360deg为一整圈。rad(弧度):2π rad为一整圈(约6.2832rad)。turn(圈):1turn为一整圈。
缩放:scale()
沿 X 轴和 Y 轴缩放元素。1 为原始尺寸,0 为完全不可见(但元素仍占据空间)。
1 | /* 宽度缩放到 1.5 倍,高度缩放到 0.8 倍 */ |
注意:scale() 会缩放元素的一切——包括边框、内边距、文字和子元素。缩放中心也是元素中心点。
倾斜:skew()
沿 X 轴和/或 Y 轴倾斜元素,产生“斜体”变形效果。
1 | /* 沿 X 轴倾斜 15 度 */ |
注意:skew() 的简写中若只给一个值,等同于 skewX()。该函数已不常被直接使用,更多被矩阵或工具库替代。
组合变换:空格分隔
多个变换函数可以用空格分隔,书写顺序即执行顺序(从右到左应用,但从视觉上理解为从左到右依次作用即可)。
1 | /* 先平移,再旋转,再缩放(执行顺序:右→左) */ |
1.3 transform-origin:变换原点
默认情况下,变换(旋转、缩放、倾斜)以元素的中心点为原点。transform-origin 可修改这个原点的位置。
1 | /* 以左上角为原点旋转 */ |
语法:transform-origin: <x> <y> [<z>];(z 用于 3D 变换)。
1.4 3D 变换简介
在 2D 基础上增加 Z 轴深度,需要配合 perspective(透视)才能产生近大远小的立体效果。
1 | .scene { |
常用 3D 函数:
| 函数 | 说明 |
|---|---|
translateZ(z) |
沿 Z 轴平移。 |
translate3d(x, y, z) |
3D 平移。 |
rotateX(angle) |
绕 X 轴旋转(前后翻转)。 |
rotateY(angle) |
绕 Y 轴旋转(左右翻转)。 |
rotateZ(angle) |
绕 Z 轴旋转(等同于 2D 旋转)。 |
rotate3d(x, y, z, a) |
绕任意 3D 向量旋转 a 角度。 |
scaleZ(z) / scale3d() |
Z 轴缩放 / 3D 缩放。 |
matrix3d() |
16 个值的 4×4 3D 矩阵。 |
3D 渲染上下文:给父容器设置 transform-style: preserve-3d,可使子元素的 3D 变换保持独立而非压平。
1 | .card-container { |
2. transition 过渡:让属性变化平滑发生
transition 是 CSS 中最简单的动画形式——当元素的指定属性值发生变化时(如悬停、聚焦、类名切换),过渡让这种变化在一段时间内平滑发生,而非瞬间跳变。
2.1 基本语法
transition 是一个简写属性:
1 | transition: <property> <duration> <timing-function> <delay>; |
1 | .button { |
2.2 四个子属性详解
| 子属性 | 说明 | 默认值 |
|---|---|---|
transition-property |
指定哪些 CSS 属性应用过渡。all 表示所有可动画属性。推荐精确指定属性,避免不必要的性能开销。 |
all |
transition-duration |
过渡持续时间。单位为 s(秒)或 ms(毫秒)。0s 表示无过渡。 |
0s |
transition-timing-function |
时间函数,控制过渡中间各时刻的速率变化。 | ease |
transition-delay |
延迟多久后开始过渡。正值延迟开始,负值立即开始但直接跳到对应时刻的状态。 | 0s |
多个属性的独立过渡:用逗号分隔,可对每个属性设置不同的过渡参数。
1 | .card { |
2.3 可过渡的属性
并非所有 CSS 属性都能平滑过渡。通常,数值型或可量化的属性才支持过渡:
| 类别 | 示例属性 | 不可过渡的典型属性 |
|---|---|---|
| 尺寸与间距 | width、height、margin、padding |
display、position |
| 颜色 | color、background-color、border-color |
background-image、font-family |
| 变换 | transform |
|
| 透明度 | opacity |
|
| 位置 | top、left、right、bottom(需定位元素) |
float |
| 其他 | box-shadow、border-radius、filter、visibility |
性能提示:在过渡或动画中,优先使用 transform 和 opacity,因为它们仅触发合成,不触发布局或绘制。避免过渡 width、height、top、left 等触发布局的属性。
3. transition-timing-function 与贝塞尔曲线
时间函数是过渡的“性格”所在——它决定了动画在时间轴上的速率分布。
3.1 预设关键字
| 关键字 | 对应曲线 | 视觉感受 |
|---|---|---|
linear |
cubic-bezier(0, 0, 1, 1) |
全程匀速,机械感强。 |
ease |
cubic-bezier(0.25, 0.1, 0.25, 1) |
慢→快→慢,自然默认值。 |
ease-in |
cubic-bezier(0.42, 0, 1, 1) |
慢→快,用于元素进入屏幕。 |
ease-out |
cubic-bezier(0, 0, 0.58, 1) |
快→慢,用于元素离开屏幕或强调结束状态。 |
ease-in-out |
cubic-bezier(0.42, 0, 0.58, 1) |
慢→快→慢,对称曲线,适合循环动画。 |
3.2 贝塞尔曲线原理
cubic-bezier() 函数接受 4 个参数:(x1, y1, x2, y2),定义了一条三次贝塞尔曲线,用于将时间进度(横轴,0→1)映射为属性变化进度(纵轴,0→1)。
- 横轴(x)始终是时间比例(0 到 1)。
- 纵轴(y)是属性值比例(0 到 1,但曲线可超出此范围产生“回弹”效果)。
- P0 固定为 (0, 0),P3 固定为 (1, 1)。用户定义的 (x1, y1) 是控制点 P1,(x2, y2) 是控制点 P2。
1 | /* 自定义:快速启动,中间放缓,结尾加速 */ |
3.3 常用自定义曲线
| 效果 | 曲线 | 适用场景 |
|---|---|---|
| 弹性回弹 | cubic-bezier(0.68, -0.55, 0.27, 1.55) |
弹入弹出,活泼灵动。 |
| 快速进入 | cubic-bezier(0.4, 0, 1, 1) |
元素快速飞入。 |
| 平滑退出 | cubic-bezier(0, 0, 0.2, 1) |
Material Design 标准退出曲线。 |
| 标准曲线 | cubic-bezier(0.4, 0, 0.2, 1) |
Material Design 标准曲线。 |
4. 综合示例:悬停浮起卡片
1 | <style> |
课后练习
一、概念自测(选择题 / 填空题)
(单选) 以下哪个 CSS 属性在动画中性能最优,因为它仅触发合成阶段?
A.width
B.background-color
C.transform
D.box-shadow(单选) 关于
translate(50%, 50%)中的百分比值,以下说法正确的是?
A. 相对于父容器的宽度和高度。
B. 相对于视口的宽度和高度。
C. 相对于元素自身的宽度和高度。
D. 相对于包含块的宽度和高度。(填空) 要使元素绕其左上角旋转,应设置
transform-origin: ______ ______。(多选) 以下哪些属性可以参与
transition平滑过渡?
A.opacity
B.display
C.transform
D.color
二、AI 编程任务:编写面向 AI 的提示词
场景:你需要实现一个图片翻转卡片(Flip Card)效果。要求如下:
- 卡片正面显示一张图片(占位图),背面显示描述文字。
- 鼠标悬停时,卡片绕 Y 轴旋转 180 度,显示背面。
- 正面和背面的切换使用 3D 变换:
rotateY。 - 父容器设置
perspective提供透视效果,卡片设置transform-style: preserve-3d。 - 正反面均设置
backface-visibility: hidden防止旋转时穿透显示。 - 过渡时间 0.6 秒,时间函数使用
ease-in-out。 - 卡片尺寸固定(如 300×200px),有圆角和阴影。
任务要求:请写出一段完整的中文提示词,发送给 AI,使其生成完整的 HTML 和 CSS 代码。提示词中应明确指定透视距离、3D 变换函数、过渡参数以及正反面的定位方式(使用绝对定位叠加)。
课后练习答案
一、概念自测答案
C
- 解析:
transform仅触发合成阶段,不触发布局和绘制,由 GPU 加速,性能最优。
- 解析:
C
- 解析:
translate()的百分比值参照元素自身尺寸,这一特性常用于绝对居中。
- 解析:
top left或0 0- 解析:
transform-origin: top left将变换原点设在元素左上角。
- 解析:
A、C、D
- 解析:
opacity、transform、color均可平滑过渡。display是离散属性,无法过渡。
- 解析:
二、AI 编程任务参考答案(提示词示例)
示例提示词:
“请实现一个翻转卡片(Flip Card)组件,纯 HTML + CSS。要求:
- 卡片外层容器
.card-container设置perspective: 1000px。- 内层
.card宽 300px,高 200px,设置transform-style: preserve-3d,transition: transform 0.6s ease-in-out。- 悬停
.card-container:hover .card时,.card执行transform: rotateY(180deg)。.card-front和.card-back使用绝对定位叠放在.card内(position: absolute; inset: 0;),均设置backface-visibility: hidden。.card-back需要预先transform: rotateY(180deg)使其初始时隐藏。- 正面放一张占位图(
https://via.placeholder.com/300x200),背面放描述文字,背面背景为#f5f5f5,文字居中。- 卡片整体有圆角
12px和阴影。直接输出完整 HTML 文件。”