CSS进阶-动画与过渡
CSS动画与过渡是现代Web界面中不可或缺的一部分,它们能为用户界面增添生动性和交互感,提升用户体验。合理使用动画不仅能够吸引用户注意力,还能让界面操作更加直观。
本文将全面介绍CSS的 transition(过渡)和 animation(动画)特性,帮助你掌握从简单过渡到复杂动画的实现技巧,以及如何优化动画性能。
# 一、CSS过渡(Transition)
# 1.1 什么是过渡
过渡(Transition)允许CSS属性值在一定时间内平滑地从一个值变化到另一个值,常用于创建简单的交互效果。
基本语法:
.element {
transition: property duration timing-function delay;
}
属性说明:
transition-property:指定过渡的CSS属性名称transition-duration:过渡持续时间transition-timing-function:过渡时间函数(缓动效果)transition-delay:过渡延迟时间
# 1.2 过渡属性详解
# transition-property
指定哪些CSS属性参与过渡:
/* 单个属性 */
transition-property: opacity;
/* 多个属性 */
transition-property: opacity, transform;
/* 所有可过渡的属性 */
transition-property: all;
/* 不过渡任何属性 */
transition-property: none;
可过渡的常见属性:
- 颜色:
color、background-color、border-color - 位置:
top、right、bottom、left - 尺寸:
width、height、padding、margin - 变换:
transform - 不透明度:
opacity - 阴影:
box-shadow、text-shadow
提示
并非所有CSS属性都支持过渡。通常数值类型、颜色类型的属性可以过渡,而 display、visibility 等离散型属性则不支持。
# transition-duration
设置过渡持续时间,单位为秒(s)或毫秒(ms):
/* 单个持续时间 */
transition-duration: 0.3s;
/* 多个属性不同持续时间 */
transition-property: opacity, transform;
transition-duration: 0.3s, 0.5s;
# transition-timing-function
控制过渡速度曲线(缓动函数):
/* 预定义关键字 */
transition-timing-function: ease; /* 默认值,慢-快-慢 */
transition-timing-function: linear; /* 匀速 */
transition-timing-function: ease-in; /* 慢速开始 */
transition-timing-function: ease-out; /* 慢速结束 */
transition-timing-function: ease-in-out; /* 慢速开始和结束 */
/* 贝塞尔曲线 */
transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);
/* 步进函数 */
transition-timing-function: steps(4, end);
常用贝塞尔曲线:
| 效果 | cubic-bezier值 | 说明 |
|---|---|---|
| ease | (0.25, 0.1, 0.25, 1) | 平滑过渡 |
| linear | (0, 0, 1, 1) | 线性过渡 |
| ease-in | (0.42, 0, 1, 1) | 加速 |
| ease-out | (0, 0, 0.58, 1) | 减速 |
| ease-in-out | (0.42, 0, 0.58, 1) | 先加速后减速 |
# transition-delay
设置过渡延迟时间:
transition-delay: 0s; /* 立即开始 */
transition-delay: 0.5s; /* 延迟0.5秒 */
transition-delay: -0.5s; /* 负延迟:跳过前0.5秒 */
# 1.3 过渡简写语法
/* 完整写法 */
.element {
transition-property: all;
transition-duration: 0.3s;
transition-timing-function: ease;
transition-delay: 0s;
}
/* 简写形式 */
.element {
transition: all 0.3s ease 0s;
}
/* 多个属性不同配置 */
.element {
transition:
opacity 0.3s ease,
transform 0.5s cubic-bezier(0.25, 0.1, 0.25, 1);
}
# 1.4 实战示例
# 按钮悬停效果
# 卡片展开效果
# 二、CSS动画(Animation)
# 2.1 什么是CSS动画
CSS动画通过 @keyframes 规则定义动画序列,使用 animation 属性应用到元素上,可以创建更复杂的动画效果。
与过渡的区别:
- 过渡需要触发(如
:hover),动画可以自动播放 - 过渡只有开始和结束两个状态,动画可以定义多个关键帧
- 动画可以循环播放、反向播放等
# 2.2 定义关键帧
使用 @keyframes 定义动画序列:
/* 使用百分比 */
@keyframes slidein {
0% {
transform: translateX(0);
opacity: 0;
}
50% {
opacity: 0.5;
}
100% {
transform: translateX(100px);
opacity: 1;
}
}
/* 使用 from/to */
@keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
# 2.3 动画属性详解
# animation-name
指定要使用的 @keyframes 名称:
animation-name: slidein;
animation-name: none; /* 不应用动画 */
# animation-duration
动画持续时间:
animation-duration: 2s; /* 2秒 */
animation-duration: 500ms; /* 500毫秒 */
# animation-timing-function
动画速度曲线,与 transition-timing-function 相同:
animation-timing-function: ease;
animation-timing-function: linear;
animation-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
# animation-delay
动画延迟时间:
animation-delay: 0s; /* 立即开始 */
animation-delay: 1s; /* 延迟1秒 */
animation-delay: -1s; /* 负延迟:跳过第1秒 */
# animation-iteration-count
动画播放次数:
animation-iteration-count: 1; /* 播放1次 */
animation-iteration-count: 3; /* 播放3次 */
animation-iteration-count: infinite; /* 无限循环 */
# animation-direction
动画播放方向:
animation-direction: normal; /* 正向播放 */
animation-direction: reverse; /* 反向播放 */
animation-direction: alternate; /* 正向-反向交替 */
animation-direction: alternate-reverse; /* 反向-正向交替 */
# animation-fill-mode
动画结束后的状态:
animation-fill-mode: none; /* 默认,不保持任何状态 */
animation-fill-mode: forwards; /* 保持最后一帧状态 */
animation-fill-mode: backwards; /* 在延迟期间应用第一帧状态 */
animation-fill-mode: both; /* 同时应用forwards和backwards */
# animation-play-state
控制动画播放状态:
animation-play-state: running; /* 播放 */
animation-play-state: paused; /* 暂停 */
# 2.4 动画简写语法
/* 完整写法 */
.element {
animation-name: slidein;
animation-duration: 2s;
animation-timing-function: ease-in-out;
animation-delay: 0s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-fill-mode: both;
}
/* 简写形式 */
.element {
animation: slidein 2s ease-in-out 0s infinite alternate both;
}
/* 多个动画 */
.element {
animation:
slidein 2s ease-in-out infinite,
fadein 1s ease;
}
# 2.5 实战示例
# 加载动画
# 悬浮动画
# 文字动画
# 三、高级动画技巧
# 3.1 多步动画
创建包含多个阶段的复杂动画:
@keyframes complex-animation {
0% {
transform: translateX(0) rotate(0deg);
background-color: #3498db;
}
25% {
transform: translateX(100px) rotate(90deg);
background-color: #e74c3c;
}
50% {
transform: translateX(100px) translateY(100px) rotate(180deg);
background-color: #2ecc71;
}
75% {
transform: translateX(0) translateY(100px) rotate(270deg);
background-color: #f39c12;
}
100% {
transform: translateX(0) translateY(0) rotate(360deg);
background-color: #3498db;
}
}
# 3.2 动画组合
组合多个动画创建复杂效果:
# 3.3 动画序列
使用 animation-delay 创建动画序列:
# 3.4 动画暂停与控制
通过JavaScript控制动画的播放状态:
# 四、性能优化
# 4.1 使用transform和opacity
为了获得最佳性能,优先使用 transform 和 opacity 属性,它们可以利用GPU加速:
/* ✅ 高性能:使用transform */
.element {
transform: translateX(100px);
transition: transform 0.3s;
}
/* ❌ 低性能:改变布局属性 */
.element {
left: 100px;
transition: left 0.3s;
}
推荐使用的属性:
transform(translate、rotate、scale)opacityfilter(某些情况)
避免动画的属性:
width、heighttop、left、right、bottommargin、paddingborder-width
# 4.2 will-change属性
使用 will-change 提示浏览器即将发生的变化,让浏览器提前优化:
.element {
will-change: transform, opacity;
}
/* 动画开始前添加 */
.element:hover {
will-change: transform;
}
/* 动画结束后移除 */
.element {
transition: transform 0.3s;
}
.element.transitioning {
will-change: transform;
}
注意
不要过度使用 will-change,它会消耗额外的内存。只在确实需要优化的元素上使用,并在动画结束后移除。
# 4.3 减少重绘和回流
触发回流(Reflow)的操作:
- 改变几何属性:
width、height、padding、margin、border - 改变字体:
font-size、font-weight - 添加或删除DOM元素
- 读取某些属性:
offsetWidth、scrollTop等
触发重绘(Repaint)的操作:
- 改变颜色:
color、background-color - 改变可见性:
visibility - 改变轮廓:
outline
优化建议:
/* ✅ 使用transform替代位置属性 */
.element {
transform: translateX(100px);
}
/* ❌ 避免频繁修改位置属性 */
.element {
left: 100px;
}
/* ✅ 使用opacity替代visibility */
.element {
opacity: 0;
pointer-events: none;
}
/* ❌ visibility会触发重绘 */
.element {
visibility: hidden;
}
# 4.4 使用requestAnimationFrame
在JavaScript中使用 requestAnimationFrame 而不是 setTimeout 或 setInterval:
// ✅ 推荐:使用requestAnimationFrame
function animate() {
element.style.transform = `translateX(${position}px)`;
position += 1;
if (position < 300) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
// ❌ 不推荐:使用setTimeout
function animate() {
element.style.transform = `translateX(${position}px)`;
position += 1;
if (position < 300) {
setTimeout(animate, 16);
}
}
# 4.5 性能测试
使用浏览器开发者工具的Performance面板监测动画性能:
// 在控制台测试FPS
let lastTime = performance.now();
let frames = 0;
function measureFPS() {
frames++;
const currentTime = performance.now();
if (currentTime >= lastTime + 1000) {
const fps = Math.round((frames * 1000) / (currentTime - lastTime));
console.log(`FPS: ${fps}`);
frames = 0;
lastTime = currentTime;
}
requestAnimationFrame(measureFPS);
}
measureFPS();
性能目标
- 保持60FPS(每帧约16.67ms)
- 避免长时间的布局计算(>50ms)
- 减少合成层(composite layers)的数量
# 五、最佳实践
# 5.1 动画设计原则
# 有目的的动画
动画应该服务于用户体验,而不是仅仅为了"好看":
- 反馈:确认用户操作(按钮点击、表单提交)
- 引导:吸引注意力到重要元素
- 关系:展示元素之间的关系(父子、顺序)
- 连续性:保持界面变化的连贯性
# 动画时长建议
根据动画类型选择合适的时长:
| 动画类型 | 建议时长 | 说明 |
|---|---|---|
| 微交互 | 100-300ms | 按钮悬停、小元素移动 |
| 中等动画 | 300-500ms | 卡片展开、菜单显示 |
| 大型动画 | 500-800ms | 页面过渡、复杂变化 |
| 背景动画 | 1s+ | 装饰性、循环动画 |
/* 微交互 */
.button {
transition: background-color 0.2s;
}
/* 中等动画 */
.modal {
animation: fadeIn 0.4s ease;
}
/* 大型动画 */
.page-transition {
animation: slideIn 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
# 5.2 缓动函数选择
不同场景使用不同的缓动函数:
/* 入场动画:ease-out(快速开始,慢速结束) */
.fade-in {
animation: fadeIn 0.4s ease-out;
}
/* 出场动画:ease-in(慢速开始,快速结束) */
.fade-out {
animation: fadeOut 0.3s ease-in;
}
/* 用户触发:ease-in-out(平滑) */
.modal {
transition: transform 0.4s ease-in-out;
}
/* 物理效果:cubic-bezier */
.bounce {
animation: bounce 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
# 5.3 响应式动画
根据设备性能和用户偏好调整动画:
/* 根据用户偏好禁用动画 */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* 在低性能设备上简化动画 */
@media (prefers-reduced-motion: no-preference) and (max-width: 768px) {
.complex-animation {
animation: simple-fade 0.3s ease;
}
}
@media (min-width: 769px) {
.complex-animation {
animation: complex-transform 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
}
# 5.4 可访问性考虑
确保动画不会影响可访问性:
/* 尊重用户的运动偏好 */
@media (prefers-reduced-motion: reduce) {
.animated {
animation: none;
transition: none;
}
}
/* 避免闪烁频率过高 */
.blink {
animation: blink 1s infinite; /* 频率 < 3Hz */
}
/* 确保动画不影响内容可读性 */
.text-animation {
animation: slide 2s ease;
/* 在动画过程中保持文字可读 */
}
# 5.5 调试技巧
使用CSS和浏览器工具调试动画:
/* 放慢动画速度便于调试 */
* {
animation-duration: 10s !important;
transition-duration: 2s !important;
}
/* 显示动画边界 */
.animated {
outline: 2px solid red;
}
/* 暂停所有动画 */
* {
animation-play-state: paused !important;
}
在浏览器开发者工具中:
- Chrome DevTools:Elements → Animations 面板
- Firefox DevTools:Inspector → Animations
- 可以放慢速度、逐帧查看、重放动画
# 六、实用动画库推荐
# 6.1 常用CSS动画库
虽然我们可以手写所有动画,但使用成熟的动画库可以提高开发效率:
# Animate.css
<!-- 引入Animate.css -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
<!-- 使用动画 -->
<div class="animate__animated animate__bounce">
弹跳效果
</div>
# Hover.css
专注于悬停效果的CSS库:
/* 模仿Hover.css的效果 */
.hvr-grow {
transition: transform 0.3s;
}
.hvr-grow:hover {
transform: scale(1.1);
}
# 6.2 JavaScript动画库
对于复杂的动画序列,可以考虑使用JavaScript库:
- GSAP:功能强大的动画库
- Anime.js:轻量级动画库
- Framer Motion:React动画库
- Motion One:现代Web动画库
# 七、浏览器兼容性
# 7.1 Transition兼容性
transition 属性在现代浏览器中有良好支持:
| 浏览器 | 支持版本 |
|---|---|
| Chrome | 26+ |
| Firefox | 16+ |
| Safari | 9+ |
| Edge | 12+ |
| IE | 10+ |
# 7.2 Animation兼容性
animation 属性同样有广泛支持:
| 浏览器 | 支持版本 |
|---|---|
| Chrome | 43+ |
| Firefox | 16+ |
| Safari | 9+ |
| Edge | 12+ |
| IE | 10+ |
# 7.3 前缀处理
对于旧版浏览器,可能需要添加前缀:
/* 手动添加前缀 */
.element {
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
-o-transition: all 0.3s;
transition: all 0.3s;
}
/* 使用Autoprefixer自动添加 */
.element {
transition: all 0.3s;
}
建议使用 Autoprefixer 等工具自动处理浏览器前缀。
# 八、总结
CSS动画与过渡是现代Web开发的重要组成部分。通过本文,我们学习了:
过渡(Transition):
- 适用于简单的状态变化
- 需要触发条件(如
:hover) - 使用
transition属性控制
动画(Animation):
- 适用于复杂的动画序列
- 使用
@keyframes定义关键帧 - 可以自动播放、循环、反向等
性能优化:
- 优先使用
transform和opacity - 合理使用
will-change - 避免触发回流和重绘
- 保持60FPS的流畅度
- 优先使用
最佳实践:
- 动画要有明确目的
- 选择合适的时长和缓动函数
- 考虑可访问性和用户偏好
- 响应式动画设计
记住:好的动画是为了增强用户体验,而不是炫技。合理使用动画,让你的网站更加生动、直观、易用。
祝你变得更强!