CSS3 动画与过渡

从静态到生动——让界面拥有生命力与回响

理解变换、过渡、关键帧,打造丝滑的现代网页交互

瞬变太廉价

你给按钮加了 :hover,鼠标移上去颜色"啪"地一下跳变——感觉卡顿、廉价,像 1990 年代的网页。怎么让它丝滑?

瞬变(廉价感)

.btn { background: #007bff; }
.btn:hover { background: #0056b3; }
/* 颜色瞬间跳变,像闪了一下 */

过渡(高级感)

.btn {
  background: #007bff;
  transition: background-color 0.3s ease;
}
/* 300ms 内平滑渐变,活了 */

这一章就解决这类问题。掌握 transform、transition、animation 三件套,你的界面会从"能用"变成"想用"。

元素形变

Transform 的 2D/3D 形变四个基本操作:位移、缩放、旋转、倾斜

/* 位移 — 最常用,不影响文档流 */
transform: translate(50px, -20px);
transform: translateX(100%);

/* 缩放 */
transform: scale(1.5);        /* 放大 1.5 倍 */
transform: scale(0.8, 1.2);   /* 宽缩高放 */

/* 旋转 */
transform: rotate(45deg);

/* 倾斜 */
transform: skew(10deg, 5deg);
组合用法:四个值可以组合使用,transform: translate(-50%, -50%) rotate(45deg) scale(1.2) ——从左到右依次执行。

形变实战

Transform 最常用的三种微交互:居中、上浮、旋转——威力在于 hover 与状态切换

卡片居中(地球上最经典的 CSS 问题)

position: absolute; top: 50%; left: 50%;
transform: translate(-50%, -50%);

按钮/图标 hover 微交互

.btn:hover { transform: translateY(-2px); }
.card:hover { transform: scale(1.02); }
.icon:hover { transform: rotate(180deg); }
黄金原则:用 transform 替代 left/top/margin 做动画——前者走 GPU 加速,后者触发页面重排,性能差 10 倍。

变换的锚点

transform-origin 控制变换的"支点"——同一个 rotate,锚点不同,效果天差地别

/* 默认绕中心旋转 */
.icon { transform: rotate(45deg); }
/* 等价于显式写出 */
.icon { transform-origin: 50% 50%; transform: rotate(45deg); }

/* 绕左上角旋转 → 像翻页 */
.page { transform-origin: left center; transform: rotateY(-30deg); }

/* 绕底部中心放大 → 像从地面升起 */
.menu { transform-origin: bottom center; transform: scaleY(1.3); }
取值效果
center center(默认)绕中心点变换
left top绕左上角
right bottom绕右下角
50% 0绕顶部中点

过渡入门

Transition 让变化有温度——状态跳变是冰冷的,过渡让操作有了"回响"

无过渡(突変)

.btn { background: #007bff; }
.btn:hover { background: #0056b3; }
/* 颜色瞬间跳变 → 用户感觉"卡"了一下 */

有过渡(丝滑)

.btn {
  background: #007bff;
  transition: background-color 0.3s ease;
}
/* 颜色在 300ms 内匀速渐变 → 高级感 */

四个子属性

transition 控制着"怎么变、变多快、何时开始"

属性作用常用值
transition-property哪个属性要过渡all / background-color / transform
transition-duration过渡持续多久0.2s / 0.3s / 1s
transition-timing-function速度曲线ease / linear / ease-in-out / cubic-bezier()
transition-delay延迟多久后开始0s / 0.5s
/* 简写顺序:property duration timing-function delay */
transition: all 0.3s ease 0s;

缓动曲线

timing-function 决定运动的"情绪"——同样的时间,加速 vs 减速,情感完全不同

/* 预定义关键词 */
transition: transform 0.3s ease;          /* 默认:先快后慢 */
transition: transform 0.3s linear;        /* 匀速:机械感 */
transition: transform 0.3s ease-in;       /* 慢入:退出、消失 */
transition: transform 0.3s ease-out;      /* 慢出:进入、出现 */
transition: transform 0.3s ease-in-out;   /* 慢入慢出:卡片 */

/* 自定义贝塞尔曲线 */
transition: transform 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55); /* 回弹 */
曲线适用场景
ease-out元素进入视图、弹窗弹出
ease-in元素离开视图、弹窗关闭
ease-in-out位置切换、状态切换
回弹贝塞尔按钮按下、通知提醒、惊喜元素
调试工具:cubic-bezier.com — 可视化拖拽曲线,复制粘贴即用。

可动画属性

哪些属性能做过渡,哪些不能——牢记这张表,做动画不走弯路

✅ 可动画(性能好,首选)⚠ 可动画但性能差❌ 不可动画
transform(translate/scale/rotate)width / heightdisplay
opacitymargin / paddingfont-family
color / background-colortop / leftposition
box-shadowfloat
border-radius、filter
注意:为什么不用 display none→block? 因为 display 不是连续值。替代方案:opacity + visibility 组合。

按钮与卡片

实战:打造一套丝滑的 hover 效果合集,直接用在你的个人主页上

/* 主按钮:上浮 + 阴影 */
.btn-primary {
  background: #D06519; color: #fff; border: none;
  padding: 12px 28px; border-radius: 8px;
  transition: all 0.3s ease;
}
.btn-primary:hover {
  transform: translateY(-3px);
  box-shadow: 0 6px 20px rgba(208, 101, 25, 0.4);
}

/* 卡片:浮起 */
.card {
  transition: transform 0.35s ease, box-shadow 0.35s ease;
}
.card:hover {
  transform: translateY(-6px);
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.12);
}

/* 链接:下划线滑出 */
.link { position: relative; }
.link::after {
  content: ''; position: absolute;
  bottom: -2px; left: 0; width: 0; height: 2px;
  background: #D06519; transition: width 0.3s ease;
}
.link:hover::after { width: 100%; }

过渡的局限

Transition 只能两端过渡——CSS Animation 是多阶段剧本,@keyframes 是导演的指令

Transition 局限性

/* 只能做 A → B 状态跳变 */
transition: transform 0.3s ease;
/* 无法实现:A → B → C 复杂路径 */
/* 无法自动播放(依赖伪类触发) */
/* 无法暂停、反转、循环 */

Animation 解决方案

/* 定义多阶段动画 */
@keyframes slideIn {
  0%   { transform: translateX(-100%); opacity: 0; }
  50%  { transform: translateX(20px); }
  100% { transform: translateX(0); opacity: 1; }
}
.element { animation: slideIn 0.6s ease-out; }

六个子属性

掌握 animation 这 6 个子属性,就能定义复杂动画的"导演指令集"

.bounce-ball {
  animation-name: bounce;
  animation-duration: 1s;
  animation-timing-function: ease-in-out;
  animation-delay: 0s;
  animation-iteration-count: infinite;  /* 数字或 infinite */
  animation-direction: alternate;        /* normal/alternate/reverse */
  animation-fill-mode: forwards;         /* 动画结束后停留在哪 */
}

/* 简写顺序 */
animation: bounce 1s ease-in-out 0s infinite alternate forwards;
属性作用常用值
animation-name引用的 @keyframes 名称自定义名
animation-duration一次完整动画的时间0.3s / 1s / 2s
animation-timing-function速度曲线ease / cubic-bezier()
animation-iteration-count播放次数1 / 3 / infinite
animation-direction播放方向normal / alternate
animation-fill-mode动画前后的状态forwards / none

旋转加载器

实战:纯 CSS 实现 loading——一个 div + 一圈边框 + keyframes = 完整动画

<div class="loader"></div>

.loader {
  width: 40px; height: 40px;
  border: 4px solid #e5e7eb;
  border-top-color: #D06519;        /* 顶部高亮 */
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
原理:四个边框三个透明,顶部着色 → 旋转时就像在转动。修改 border 颜色和 width 可以做出各种变体。

渐显入场动画

实战:用 animation-delay 创造错落有致的列表入场效果

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.card {
  animation: fadeInUp 0.5s ease-out forwards;
  opacity: 0;  /* 初始不可见,动效完成后 forwards 保留 */
}

/* 5 张卡片错落出现 */
.card:nth-child(1) { animation-delay: 0s; }
.card:nth-child(2) { animation-delay: 0.1s; }
.card:nth-child(3) { animation-delay: 0.2s; }
/* ... 依次加 0.1s → 瀑布般的入场效果 */

GPU 加速

will-change 是 GPU 加速的最后钥匙——告诉浏览器"这个元素即将动画",浏览器提前分配资源

/* 告诉浏览器:这个元素即将做 transform 变化 */
.card {
  will-change: transform;      /* 提前分配 GPU */
  transition: transform 0.3s ease;
}

/* ❌ 滥用 will-change → 内存暴涨,性能更差 */
* { will-change: transform; }   /* 千万别这样做! */

/* ✅ 只在即将动画的元素上使用 */
.box:hover { will-change: transform; }
.box:not(:hover) { will-change: auto; }
注意:滥用 will-change 的后果:浏览器为每个声明的元素分配 GPU 显存,内存暴涨 + 卡顿。原则:只对'即将发生动画'的元素声明,动画结束后清除。

体谅不动画

prefers-reduced-motion——为不想看动画的用户(前庭功能障碍、癫痫)提供无动画体验

/* 为所有人添加动画 */
.card {
  animation: fadeInUp 0.5s ease-out forwards;
}

/* 尊重'减少动画'系统设置 */
@media (prefers-reduced-motion: reduce) {
  .card {
    animation: none;          /* 关闭动画 */
    opacity: 1;               /* 确保内容立即可见 */
    transform: none;
  }
}
为什么重要:根据 WHO 估计,全球约 15% 的人口有不同程度的前庭功能障碍。闪烁/旋转/快速平移可能触发眩晕甚至癫痫。一个专业的开发者会为这些用户提供无动画的替代体验。

动画三件套到手

transform

translate/scale/rotate + GPU 加速

transition

四大属性 + 缓动曲线 + 性能

animation + @keyframes

多阶段剧本 + 实战案例

will-change

何时用、何时不用

prefers-reduced-motion

让网页对所有人都友好

知识学会了,下一章你将学习如何借助 AI 的力量,对网页进行精准的渐进式设计和生成。

下一章:渐进式引导生成 →

← 上一章 1 / 17 下一章 →