CSS过渡与简单动画

张玥 2025年9月14日 阅读时间 45分钟
CSS3 过渡 动画 前端开发
CSS过渡与动画示例

CSS过渡与动画是现代Web开发中不可或缺的技术,它们为用户界面增添了生动性和交互性。 本文将全面介绍CSS过渡(transition)和动画(animation)的基本概念、语法、属性以及实际应用场景。 无论你是初学者还是有经验的开发者,都能从本文中获得关于创建流畅、吸引人用户体验的实用知识。

CSS过渡(Transition)基础

CSS过渡允许你在一定时间内平滑地改变属性值,而不是瞬间变化。这是创建微妙动画效果最简单的方式。

/* 基本过渡语法 */
.element {
  transition: property duration timing-function delay;
}

/* 过渡属性分解 */
.element {
  transition-property: all; /* 指定要过渡的属性 */
  transition-duration: 0.3s; /* 过渡持续时间 */
  transition-timing-function: ease; /* 过渡速度曲线 */
  transition-delay: 0s; /* 过渡开始前的延迟 */
}

/* 实际应用示例 */
.button {
  background-color: #2563eb;
  color: white;
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  transition: background-color 0.3s ease, transform 0.2s ease-out;
}

.button:hover {
  background-color: #1d4ed8;
  transform: translateY(-2px);
}

悬停查看过渡效果:

悬停我

这个示例展示了颜色、尺寸、形状和旋转的同时过渡效果。

可设置过渡的CSS属性:

  • 尺寸相关:width, height, padding, margin, font-size
  • 颜色相关:color, background-color, border-color
  • 位置相关:top, right, bottom, left
  • 变换相关:transform, opacity, visibility
  • 布局相关:flex, grid 相关属性(部分浏览器支持有限)

过渡计时函数(Timing Functions)

过渡计时函数决定了动画过程中值的变化速度,直接影响动画的"感觉"和流畅度。

/* 预定义的计时函数 */
.element {
  transition-timing-function: ease; /* 默认,慢快慢 */
}

.element {
  transition-timing-function: linear; /* 匀速 */
}

.element {
  transition-timing-function: ease-in; /* 慢开始 */
}

.element {
  transition-timing-function: ease-out; /* 慢结束 */
}

.element {
  transition-timing-function: ease-in-out; /* 慢开始和结束 */
}

/* 自定义贝塞尔曲线 */
.element {
  transition-timing-function: cubic-bezier(0.17, 0.67, 0.83, 0.67);
}

/* 步进函数 */
.element {
  transition-timing-function: steps(4, end);
}

不同计时函数对比:

linear
ease
ease-in
ease-out
ease-in-out

注意观察每个方块运动速度的变化模式。

选择合适计时函数的技巧:

  • ease:最适合大多数UI元素的默认选择
  • ease-in:适用于离开屏幕或消失的元素
  • ease-out:适用于进入屏幕或出现的元素
  • linear:适用于颜色或透明度变化,机械运动
  • 自定义曲线:创建独特品牌个性或特殊效果

CSS动画(Animation)基础

CSS动画比过渡更强大,允许创建复杂的多阶段动画,无需用户交互即可自动播放。

/* 定义关键帧动画 */
@keyframes slide-in {
  0% {
    transform: translateX(-100%);
    opacity: 0;
  }
  70% {
    transform: translateX(10%);
  }
  100% {
    transform: translateX(0);
    opacity: 1;
  }
}

/* 应用动画 */
.element {
  animation-name: slide-in;
  animation-duration: 1s;
  animation-timing-function: ease-out;
  animation-delay: 0.5s;
  animation-iteration-count: infinite; /* 或数字 */
  animation-direction: alternate; /* normal, reverse, alternate, alternate-reverse */
  animation-fill-mode: both; /* none, forwards, backwards, both */
  animation-play-state: running; /* running 或 paused */
}

/* 简写形式 */
.element {
  animation: slide-in 1s ease-out 0.5s infinite alternate both;
}

CSS动画示例:

这个方块使用了无限循环的脉动动画效果。

动画属性详解:

  • animation-name:指定要应用的@keyframes动画名称
  • animation-duration:动画完成一个周期所需时间
  • animation-timing-function:动画速度曲线(同过渡)
  • animation-delay:动画开始前的延迟时间
  • animation-iteration-count:动画播放次数(数字或infinite)
  • animation-direction:动画播放方向(正常、反向、交替等)
  • animation-fill-mode:动画执行前后如何应用样式
  • animation-play-state:允许暂停和恢复动画

变换(Transform)与动画结合

CSS变换属性可以改变元素的形状、位置和大小,与动画结合可以创建出令人印象深刻的视觉效果。

/* 2D变换 */
.element {
  transform: translate(100px, 50px); /* 移动 */
  transform: rotate(45deg); /* 旋转 *//* 缩放 */
  transform: scale(1.5); /* 等比例缩放 */
  transform: scaleX(1.5); /* 水平缩放 */
  transform: scaleY(1.5); /* 垂直缩放 */
  transform: skew(30deg, 20deg); /* 倾斜 */
}

/* 变换原点 */
.element {
  transform-origin: center center; /* 默认 */
  transform-origin: left top; /* 左上角 */
  transform-origin: 100px 200px; /* 具体坐标 */
}

/* 多重变换 */
.element {
  transform: translateX(100px) rotate(45deg) scale(1.2);
}

/* 3D变换 */
.parent {
  perspective: 1000px; /* 3D透视 */
}

.element {
  transform: rotateX(45deg) rotateY(30deg);
  transform-style: preserve-3d; /* 保持3D空间 */
}

变换效果示例:

悬停查看变换

这个示例结合了平移、旋转和倾斜变换。

变换与动画结合的最佳实践:

  • 使用transformopacity属性制作动画,性能最佳
  • 避免动画期间改变布局属性(width、height、margin等),会导致重排
  • 使用will-change属性提示浏览器哪些属性将变化,优化性能
  • 考虑使用translate3d()开启GPU加速,但不要过度使用
  • 对于复杂动画,考虑使用CSS动画而不是JavaScript以获得更好性能

实际应用案例

下面是一些在实际项目中应用CSS过渡和动画的常见场景。

加载动画

/* 旋转加载器 */
.loader {
  width: 40px;
  height: 40px;
  border: 4px solid #f3f3f3;
  border-top: 4px solid #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* 点状加载动画 */
.dot-flashing {
  position: relative;
  width: 10px;
  height: 10px;
  border-radius: 5px;
  background-color: #2563eb;
  color: #2563eb;
  animation: dotFlashing 1s infinite linear alternate;
  animation-delay: 0.5s;
}

.dot-flashing::before, .dot-flashing::after {
  content: '';
  display: inline-block;
  position: absolute;
  top: 0;
  width: 10px;
  height: 10px;
  border-radius: 5px;
  background-color: #2563eb;
  color: #2563eb;
}

.dot-flashing::before {
  left: -15px;
  animation: dotFlashing 1s infinite alternate;
  animation-delay: 0s;
}

.dot-flashing::after {
  left: 15px;
  animation: dotFlashing 1s infinite alternate;
  animation-delay: 1s;
}

@keyframes dotFlashing {
  0% { background-color: #2563eb; }
  50%, 100% { background-color: #dbeafe; }
}

加载动画示例:

左侧是旋转加载器,右侧是点状加载动画。

交互反馈动画

/* 按钮点击涟漪效果 */
.ripple-button {
  position: relative;
  overflow: hidden;
  background-color: #2563eb;
  color: white;
  border: none;
  padding: 12px 24px;
  border-radius: 4px;
  cursor: pointer;
}

.ripple-button .ripple {
  position: absolute;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.7);
  transform: scale(0);
  animation: ripple 0.6s linear;
}

@keyframes ripple {
  to {
    transform: scale(4);
    opacity: 0;
  }
}

/* 卡片悬停效果 */
.card {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  transition: all 0.3s ease;
}

.card:hover {
  transform: translateY(-5px);
  box-shadow: 0 10px 20px rgba(0,0,0,0.15);
}

交互反馈示例:

悬停卡片

将鼠标悬停在此卡片上查看效果

性能优化与最佳实践

性能考虑

  • 优先使用transformopacity属性制作动画,它们不会触发布局或绘制
  • 避免动画期间改变盒模型属性(width、height、padding等),会导致性能下降
  • 使用will-change属性小心地提示浏览器哪些属性将变化
  • 尽量减少同时运行的动画数量,特别是在低性能设备上
  • 适当使用animation-play-state: paused暂停不可见元素的动画

可访问性考虑

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

/* 或者提供替代的简化动画 */
@media (prefers-reduced-motion: reduce) {
  .animated-element {
    animation: fade-in 0.5s ease-out;
  }
}

调试技巧

  • 使用浏览器开发者工具中的Animations面板调试CSS动画
  • 使用animation-play-state: paused在特定时间点检查动画状态
  • 逐步增加动画复杂度,先实现基本效果再添加细节
  • 在不同设备和浏览器上测试动画性能和外观
  • 考虑使用CSS动画库(如Animate.css)作为起点