CSS动画与过渡效果完全指南

CSS教程 作者: 编辑团队 发布于: 2026-07-09 阅读约 13 分钟

CSS 动画概述

CSS动画是Web开发中提升用户体验的重要手段。通过CSS Transitions(过渡)和CSS Animations(动画),可以实现流畅的视觉效果,无需依赖JavaScript。正确使用动画可以引导用户注意力、提供交互反馈、增强界面的层次感。

CSS Transitions(过渡)

CSS过渡可以在属性值变化时创建平滑的动画效果。它适用于状态切换(如hover、focus)时的动画。

transition 属性详解

.button {
  background-color: #3b82f6;
  color: white;
  padding: 12px 24px;
  border: none;
  border-radius: 8px;

  /* transition 简写 */
  transition: all 0.3s ease;

  /* 或分别指定 */
  /* transition-property: background-color, transform; */
  /* transition-duration: 0.3s; */
  /* transition-timing-function: ease; */
  /* transition-delay: 0s; */
}

.button:hover {
  background-color: #2563eb;
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4);
}

.button:active {
  transform: translateY(0);
}

transition-property — 过渡属性

说明
all 所有可动画属性都会过渡(性能警告)
none 不应用过渡
transform 仅过渡transform属性(推荐,GPU加速)
opacity 仅过渡透明度(推荐,GPU加速)
background-color, color 指定多个属性,逗号分隔

transition-timing-function — 缓动函数

/* 预设缓动函数 */
.ease       { transition-timing-function: ease; }        /* 默认:慢-快-慢 */
.ease-in    { transition-timing-function: ease-in; }     /* 慢速开始 */
.ease-out   { transition-timing-function: ease-out; }    /* 慢速结束 */
.ease-in-out { transition-timing-function: ease-in-out; } /* 慢速开始和结束 */
.linear     { transition-timing-function: linear; }      /* 匀速 */

/* 贝塞尔曲线自定义 */
.custom {
  transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

/* 弹性效果 */
.bounce {
  transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);
}

实用过渡模式

/* 淡入效果 */
.fade-in {
  opacity: 0;
  transition: opacity 0.4s ease;
}
.fade-in.visible {
  opacity: 1;
}

/* 滑入效果 */
.slide-up {
  transform: translateY(20px);
  opacity: 0;
  transition: transform 0.4s ease, opacity 0.4s ease;
}
.slide-up.visible {
  transform: translateY(0);
  opacity: 1;
}

/* 缩放效果 */
.scale:hover {
  transform: scale(1.05);
  transition: transform 0.2s ease;
}

/* 下划线动画 */
.link {
  position: relative;
  text-decoration: none;
}
.link::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0;
  height: 2px;
  background: var(--accent);
  transition: width 0.3s ease;
}
.link:hover::after {
  width: 100%;
}

CSS Animations(动画)

CSS动画通过 @keyframes 定义关键帧,可以创建更复杂、更灵活的动画效果,支持自动播放、循环、延迟等。

@keyframes 定义

/* 基本淡入动画 */
@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 使用百分比定义多阶段动画 */
@keyframes slideIn {
  0% {
    transform: translateX(-100%);
    opacity: 0;
  }
  50% {
    opacity: 1;
  }
  100% {
    transform: translateX(0);
    opacity: 1;
  }
}

/* 旋转动画 */
@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* 脉冲动画 */
@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.05); }
}

animation 属性详解

.animated-element {
  /* animation 简写 */
  animation: fadeIn 0.6s ease-out forwards;

  /* 或分别指定 */
  animation-name: fadeIn;
  animation-duration: 0.6s;
  animation-timing-function: ease-out;
  animation-delay: 0.2s;
  animation-fill-mode: forwards;  /* 保持结束状态 */
  animation-iteration-count: 1;   /* 播放一次 */
  animation-direction: normal;    /* 正常方向 */
}

/* animation-fill-mode 说明 */
.fill-none    { animation-fill-mode: none; }      /* 默认:不应用初始/结束状态 */
.fill-forwards { animation-fill-mode: forwards; } /* 保持结束状态 */
.fill-backwards { animation-fill-mode: backwards; } /* 应用初始状态(包括delay期间) */
.fill-both    { animation-fill-mode: both; }      /* 两者都应用 */

animation-iteration-count 和 direction

/* 无限循环 */
.loading-spinner {
  animation: spin 1s linear infinite;
}

/* 播放3次 */
.retry-button {
  animation: shake 0.5s ease-in-out 3;
}

/* 交替方向 */
.alternating {
  animation: pulse 2s ease-in-out infinite alternate;
}

/* 反向播放 */
.reverse {
  animation: slideIn 0.6s ease-out reverse;
}

CSS Transform 变换

Transform是CSS动画的核心,可以对元素进行2D和3D变换。

2D Transform

.rotate {
  transform: rotate(45deg);
}

.scale {
  transform: scale(1.5);
}

.translate {
  transform: translate(20px, 10px);
}

.skew {
  transform: skew(10deg, 5deg);
}

/* 组合变换 */
.combined {
  transform: rotate(45deg) scale(1.5) translate(20px, 0);
}

3D Transform

/* 3D空间需要父容器设置perspective */
.perspective-container {
  perspective: 1000px;
}

.card-3d {
  transform-style: preserve-3d;
  transition: transform 0.6s ease;
}

.card-3d:hover {
  transform: rotateY(15deg) rotateX(5deg);
}

/* 翻转效果 */
.flip-card {
  position: relative;
  width: 200px;
  height: 200px;
}

.flip-card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transition: transform 0.6s;
  transform-style: preserve-3d;
}

.flip-card:hover .flip-card-inner {
  transform: rotateY(180deg);
}

.flip-card-front,
.flip-card-back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
}

.flip-card-back {
  transform: rotateY(180deg);
}

性能优化技巧

CSS动画的性能至关重要,错误的选择会导致页面卡顿。

GPU加速与will-change

/* 只动画 transform 和 opacity(合成层属性,GPU加速) */
.performance-optimized {
  transition: transform 0.3s ease, opacity 0.3s ease;
}

/* will-change 提示浏览器准备动画 */
.will-animate {
  will-change: transform, opacity;
}

/* 动画结束后移除will-change */
.animated.done {
  will-change: auto;
}
属性类型 包含属性 性能影响
合成层属性(推荐) transform, opacity 低:GPU加速,不触发重排重绘
绘制属性 color, background, box-shadow 中:触发重绘,但不触发重排
布局属性 width, height, margin, padding 高:触发重排(最昂贵的操作)
黄金法则:尽量只动画 transformopacity,避免动画 widthheightmargintopleft 等布局属性。

实用动画模式

加载动画

/* 旋转加载器 */
@keyframes spinner {
  to { transform: rotate(360deg); }
}

.loader {
  width: 40px;
  height: 40px;
  border: 4px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spinner 0.8s linear infinite;
}

/* 骨架屏闪烁 */
@keyframes shimmer {
  0% { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

.skeleton {
  background: linear-gradient(90deg,
    var(--bg-elevated) 25%,
    var(--bg-hover) 50%,
    var(--bg-elevated) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 4px;
}

入场动画

/* 交错入场效果 */
.stagger-item {
  opacity: 0;
  transform: translateY(20px);
  animation: fadeInUp 0.5s ease forwards;
}

.stagger-item:nth-child(1) { animation-delay: 0.1s; }
.stagger-item:nth-child(2) { animation-delay: 0.2s; }
.stagger-item:nth-child(3) { animation-delay: 0.3s; }
.stagger-item:nth-child(4) { animation-delay: 0.4s; }

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

/* 使用JS Intersection Observer 触发 */
<script>
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('animate');
      observer.unobserve(entry.target);
    }
  });
}, { threshold: 0.1 });

document.querySelectorAll('.animate-on-scroll').forEach(el => {
  observer.observe(el);
});
</script>

微交互

/* 按钮点击波纹效果 */
.ripple-button {
  position: relative;
  overflow: hidden;
}

.ripple-button::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  background: rgba(255, 255, 255, 0.3);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  transition: width 0.4s ease, height 0.4s ease;
}

.ripple-button:active::after {
  width: 300px;
  height: 300px;
}

/* 数字计数动画(配合CSS counter) */
@keyframes countUp {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.counter {
  animation: countUp 0.3s ease-out;
  font-variant-numeric: tabular-nums;
}

减少动画的无障碍考虑

/* 尊重用户的减少动画偏好 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* 或者只禁用特定动画 */
@media (prefers-reduced-motion: reduce) {
  .animated-element {
    animation: none;
    transition: none;
  }
}

最佳实践总结

  1. 只动画 transform 和 opacity,避免触发重排的属性
  2. 使用 will-change 提示浏览器准备动画(但不要滥用)
  3. 动画时长控制在300-500ms,太慢会让人等待,太快看不清
  4. 使用 ease-out 作为入场动画的缓动,ease-in 用于退场
  5. 始终添加 prefers-reduced-motion 媒体查询
  6. 为动画元素预留空间,避免布局偏移
  7. 使用CSS变量管理动画参数,便于统一调整
  8. 在动画结束后清理:移除 will-change、清理类名