CSS 动画实战
CSS 动画概述
CSS 动画可以创建流畅的交互效果,无需 JavaScript。从简单的过渡效果到复杂的逐帧动画,CSS 都能胜任。相比 JS 动画,CSS 动画可以利用 GPU 加速,性能更好。
transition 过渡
基础用法
.button {
background-color: blue;
color: white;
padding: 10px 20px;
border: none;
transition: background-color 0.3s ease;
}
.button:hover {
background-color: darkblue;
}
transition 属性详解
.element {
/* 单个属性 */
transition: opacity 0.3s ease;
/* 多个属性 */
transition: transform 0.3s ease, background-color 0.2s linear;
/* 全部属性 */
transition: all 0.3s ease;
/* 详细写法 */
transition-property: transform, opacity;
transition-duration: 0.3s, 0.2s;
transition-timing-function: ease, linear;
transition-delay: 0s, 0.1s;
}
缓动函数
.ease { transition-timing-function: ease; } /* 慢-快-慢 */
.linear { transition-timing-function: linear; } /* 匀速 */
.ease-in { transition-timing-function: ease-in; } /* 慢到快 */
.ease-out { transition-timing-function: ease-out; } /* 快到慢 */
.ease-in-out{ transition-timing-function: ease-in-out; } /* 更平缓的慢-快-慢 */
/* 贝塞尔曲线:自定义缓动 */
.custom { transition-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55); }
/* 弹跳效果 */
/* 阶跃函数:逐帧动画 */
.steps { transition-timing-function: steps(4, end); }
transition 触发条件
:hover、:focus、:active等伪类- 类名切换(如
.active) - JavaScript 动态修改样式
keyframes 关键帧动画
基本语法
@keyframes slideIn {
from {
transform: translateX(-100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.element {
animation: slideIn 0.5s ease-out;
}
多关键帧
@keyframes bounce {
0% {
transform: translateY(0);
}
50% {
transform: translateY(-30px);
}
70% {
transform: translateY(-15px);
}
90% {
transform: translateY(-5px);
}
100% {
transform: translateY(0);
}
}
animation 属性
.element {
/* 简写 */
animation: slideIn 0.5s ease-out 0.2s 3 alternate forwards;
/* 详细写法 */
animation-name: slideIn;
animation-duration: 0.5s;
animation-timing-function: ease-out;
animation-delay: 0.2s;
animation-iteration-count: 3; /* 播放次数,infinite 无限 */
animation-direction: alternate; /* normal | reverse | alternate | alternate-reverse */
animation-fill-mode: forwards; /* none | forwards | backwards | both */
animation-play-state: running; /* running | paused */
}
animation-fill-mode 说明:
none:动画结束后回原位(默认)forwards:动画结束后保持最后一帧backwards:在延迟期间应用第一帧both:同时应用 forwards 和 backwards
实战案例
加载动画
.spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top-color: #3498db;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
脉冲动画
.pulse {
width: 100px;
height: 100px;
background: #3498db;
border-radius: 50%;
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.2); opacity: 0.7; }
100% { transform: scale(1); opacity: 1; }
}
进入动画
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.enter {
animation: fadeInUp 0.5s ease-out both;
}
/* 交错动画 */
.enter:nth-child(1) { animation-delay: 0s; }
.enter:nth-child(2) { animation-delay: 0.1s; }
.enter:nth-child(3) { animation-delay: 0.2s; }
.enter:nth-child(4) { animation-delay: 0.3s; }
悬浮卡片
.card {
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-8px) scale(1.02);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}
性能优化
/* 仅对 transform 和 opacity 做动画 */
.optimized {
/* ✅ 推荐:仅触发合成 */
transition: transform 0.3s ease, opacity 0.3s ease;
/* ❌ 避免:触发重排 */
/* transition: width 0.3s, height 0.3s, top 0.3s; */
}
/* 使用 will-change 提前告知 */
.animated {
will-change: transform;
}
总结
| 特性 | transition | animation |
|---|---|---|
| 触发方式 | 状态变化触发 | 自动运行 |
| 关键帧 | 起点到终点 | 多关键帧 |
| 循环 | 手动 JS 控制 | animation-iteration-count |
| 控制 | 有限 | 暂停/继续/反向 |
建议:简单交互(hover、展开/收起)用 transition,复杂动画(循环、多阶段)用 keyframes。始终优先对 transform 和 opacity 做动画以获得最佳性能。