CSS 过渡与动画
网页有了"动效"才有质感。一个按钮悬停时平滑变色上浮、一个加载图标持续旋转、一段内容淡入——这些都是 CSS 动效的功劳。这一篇讲清三大核心:transition(过渡)、transform(变换)、@keyframes(关键帧动画)。
1. transition 过渡
transition 让属性变化平滑过渡,而不是瞬间跳变。这是最高频的动效,几乎每个交互按钮都用。
/* transition:让属性变化平滑过渡,而不是瞬间跳变 */
.btn {
background: #4f8cff;
transform: translateY(0);
transition: background .2s, transform .2s;
}
.btn:hover {
background: #3a78e0;
transform: translateY(-2px); /* 悬停时上浮 2px */
}
/* transition 简写:property duration timing-function delay */
.link {
transition: color .3s ease 0s;
}
/* 全部属性都过渡(慎用,性能差) */
.box {
transition: all .3s;
}语法:transition: 属性 时长 缓动 延迟。要让多个属性都过渡,用逗号分隔。最常过渡的属性:color、background、transform、opacity、box-shadow——这些过渡很顺滑。但 width/height/margin/top 等会引起重排的属性,过渡性能差,慎用。
关键认知:transition 写在元素本身上,不是写在 :hover 里。这样鼠标移入移出都有过渡——写在 :hover 里的话,移出会瞬间跳变。
2. transform 变换
transform 用来做旋转、缩放、位移、倾斜。它不脱离文档流,也不触发重排——浏览器直接在 GPU 层合成,性能极高,是动效首选。
.icon {
/* 移动:translate(x, y) */
transform: translate(10px, 20px);
transform: translateX(10px);
transform: translateY(-50%); /* 配合 top:50% 做垂直居中 */
/* 缩放:scale 没有单位,1 是原大小 */
transform: scale(1.2); /* 放大到 1.2 倍 */
transform: scaleX(2); /* 只水平拉伸 */
/* 旋转:rotate 单位是 deg */
transform: rotate(45deg);
transform: rotate(-90deg);
/* 倾斜:skew */
transform: skew(10deg, 5deg);
/* 组合多个变换(顺序重要!) */
transform: translate(10px, 0) rotate(45deg) scale(1.1);
}
/* transform 不会触发重排,性能比改 top/left 高很多 */几个要点:
- translate:位移。
translateY(-50%)配合top: 50%是经典的"未知高度垂直居中"写法。 - scale:缩放。悬停放大
scale(1.1)是卡片悬停的标配。 - rotate:旋转。图标旋转、加载动画都用它。
- 组合变换的顺序很重要:
translate(10px,0) rotate(45deg)和rotate(45deg) translate(10px,0)效果不同——后写的"先发生"。CSS 是从右往左读变换的。
3. @keyframes 关键帧动画
transition 只能从 A 状态过渡到 B 状态。需要更复杂的动画(多个关键节点、循环播放),就要用 @keyframes + animation。
/* 定义动画:从 0% 到 100% 的关键帧 */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
/* 多个关键帧 */
@keyframes bounce {
0% { transform: translateY(0); }
50% { transform: translateY(-30px); }
100% { transform: translateY(0); }
}
/* 使用动画 */
.box {
animation: fadeIn .5s ease-out;
}
.ball {
animation: bounce 1s ease-in-out infinite; /* infinite = 无限循环 */
}@keyframes 定义动画——给关键帧起名(如 fadeIn、bounce),用 from/to 或百分比 0%/50%/100% 描述每个节点的样式。然后用 animation 把它绑到元素上。
4. animation 完整属性
animation 有 8 个子属性,简写按固定顺序排:
.loader {
/* animation 简写:
name duration timing-function delay iteration-count direction */
animation: spin 1s linear infinite;
/* 等价的完整写法 */
animation-name: spin;
animation-duration: 1s;
animation-timing-function: linear;
animation-delay: 0s;
animation-iteration-count: infinite; /* infinite 或数字 */
animation-direction: alternate; /* 反向播放 */
animation-fill-mode: forwards; /* 结束时保持最后一帧 */
animation-play-state: paused; /* 暂停 */
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}重点几个:
- iteration-count:播放次数。
infinite无限循环(加载动画必备),或写具体数字。 - direction:
alternate来回播放(先正放再反放),做"呼吸"效果。 - fill-mode:
forwards让动画停在最后一帧(默认会跳回初始状态)。 - play-state:
paused暂停——可以用 JS 控制播放暂停。
5. 缓动函数(timing-function)
缓动决定了动效"快慢节奏"。选对缓动,动效立刻专业;选错,会觉得"卡"。
/* 常用缓动函数 */
/* linear:匀速,适合加载旋转 */
transition: transform 1s linear;
/* ease:默认,慢-快-慢 */
transition: transform .3s ease;
/* ease-in:开始慢,后面快 */
transition: transform .3s ease-in;
/* ease-out:开始快,后面慢(按钮反馈常用) */
transition: transform .3s ease-out;
/* ease-in-out:两端慢中间快 */
transition: transform .3s ease-in-out;
/* cubic-bezier:自定义曲线(设计师的真爱) */
transition: transform .3s cubic-bezier(0.68, -0.55, 0.27, 1.55);实战建议:
- 加载旋转:用
linear(匀速)。 - 按钮悬停反馈:用
ease-out或cubic-bezier(快出慢收)。 - 弹性效果:用
cubic-bezier(0.68, -0.55, 0.27, 1.55)(超出再回弹)。 - 避免
ease:它是默认值但效果一般,显式写ease-out通常更好。
在线工具(cubic-bezier.com)可以可视化调曲线,调好后复制参数。
6. 动效设计原则
- 动效要快:悬停反馈一般
0.15 ~ 0.3 秒最舒服,超过 0.5 秒用户会觉得"卡"。 - 避免大面积、长时间动画:既分散注意,也影响性能。
- 动效要有意义:别为了动而动。每个动效都应该传递信息(状态变化、引导注意力)。
- prefers-reduced-motion:用
@media (prefers-reduced-motion: reduce)给对动效敏感的用户关闭动画,无障碍考量。 - 能用 transform/opacity 就别用 width/top:前者走 GPU 合成,性能远高于后者。
小结
transition 让属性变化平滑(写在元素本身)、transform 做变换(性能高)、@keyframes + animation 做关键帧动画(可循环)。记住:动效要快、要克制、要有意义。下一篇讲响应式设计——让页面适配手机、平板、桌面。
← 上一篇 CSS 定位
下一篇 CSS 响应式设计 →