CSS 动画三剑客:过渡、变换与动画

693 阅读13分钟

前言

在现代Web开发中,用户对界面的期望已经远远超越了静态的页面展示。流畅的动画效果、自然的交互反馈和富有层次感的视觉体验,已经成为优秀网站的标配。作为前端开发者,掌握CSS的动画技术是必不可少的技能。
本文将深入探讨CSS中的三大动画技术:过渡(Transition)、变换(Transform)和动画(Animation),帮助你创建流畅、优雅的用户界面。

一、CSS过渡(Transition)

(一)什么是过渡?

CSS过渡允许你在改变CSS属性时控制动画速度。它可以让属性的变化在一定时间内平滑地进行,而不是立即发生。

(二)基本语法

transition: property duration timing-function delay;
  • property: 要过渡的CSS属性
  • duration: 过渡持续时间
  • timing-function: 过渡的时间函数
  • delay: 过渡延迟时间

(三)详细属性示例

1. transition-property

指定哪些CSS属性需要应用过渡效果。可以设置单个属性、多个属性或所有属性。使用all时要注意性能,因为它会监听所有属性变化,可能导致不必要的重绘,影响性能。。

/* 单个属性 */
transition-property: width;

/* 多个属性 */
transition-property: width, height, background-color;

/* 所有属性 */
transition-property: all;

2. transition-duration

设置过渡动画的持续时间。可以使用秒(s)或毫秒(ms)作为单位。时间越长,动画越慢;时间越短,动画越快。一般建议在0.1s到0.5s之间,以获得良好的用户体验。

transition-duration: 0.3s;  /* 秒 */
transition-duration: 300ms; /* 毫秒 */

3. 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);

4. transition-delay

设置过渡动画开始前的延迟时间。在需要创建动画序列或错开多个元素的动画时非常有用。延迟时间从触发条件(如:hover)开始计算。

transition-delay: 0.1s;

(四)实际应用示例

这个示例展示了CSS过渡的基本用法,创建了一个带有悬停和点击效果的按钮。当鼠标悬停时,按钮会改变颜色、向上移动并增加阴影;点击时会有轻微的按压效果。

  • 完整演示代码:

二、CSS变换(Transform)

(一)什么是变换?

CSS变换允许你旋转、缩放、倾斜或平移元素,而不影响文档流中其他元素的位置。CSS变换主要分为两大类:

  • 2D变换

    • 在二维平面(X轴和Y轴)上进行变换
    • 包括平移(translate)、旋转(rotate)、缩放(scale)、倾斜(skew)
    • 适用于大多数常见的界面动效
    • 性能较好,兼容性强
  • 3D变换

    • 在三维空间(X轴、Y轴、Z轴)上进行变换
    • 增加了深度和透视效果
    • 需要设置透视距离(perspective)来获得3D视觉效果
    • 可以创建更加立体和真实的动画效果
    • 对浏览器性能要求较高

(二)2D变换函数

1. translate() - 平移

平移变换可以移动元素的位置,而不影响文档流中其他元素。支持像素值和百分比值,百分比是相对于元素自身的尺寸计算的。

/* 水平和垂直平移 */
transform: translate(50px, 100px);

/* 单独控制 */
transform: translateX(50px);
transform: translateY(100px);

/* 百分比值(相对于元素自身尺寸) */
transform: translate(50%, 50%);

2. rotate() - 旋转

旋转变换以元素的中心点为轴心进行旋转。正值表示顺时针旋转,负值表示逆时针旋转。单位为度(deg)或弧度(rad)。

/* 顺时针旋转45度 */
transform: rotate(45deg);

/* 逆时针旋转 */
transform: rotate(-45deg);

3. scale() - 缩放

缩放变换可以改变元素的大小。值大于1表示放大,小于1表示缩小,等于1表示保持原始大小。可以分别控制X轴和Y轴的缩放比例。

/* 等比缩放 */
transform: scale(1.5);

/* 分别控制X和Y轴 */
transform: scale(2, 0.5);
transform: scaleX(2);
transform: scaleY(0.5);

4. skew() - 倾斜

倾斜变换可以让元素沿着X轴或Y轴倾斜一定角度,创造出平行四边形的效果。常用于创建动态的视觉效果。

/* X轴倾斜 */
transform: skewX(20deg);

/* Y轴倾斜 */
transform: skewY(10deg);

/* 同时倾斜 */
transform: skew(20deg, 10deg);

(三)3D变换

1. transform-style

控制子元素是否保持3D变换效果。设置为preserve-3d时,子元素会保持在3D空间中,而不是被扁平化到父元素的平面上。

/* 保持3D变换 */
transform-style: preserve-3d;

2. perspective

设置观察者与3D元素之间的距离,创建透视效果。值越小,透视效果越强烈;值越大,透视效果越平缓。通常设置在父元素上。

/* 设置透视距离 */
perspective: 1000px;

3. 3D变换函数

3D变换函数在2D变换的基础上增加了Z轴(深度)的控制,可以创建更加立体的视觉效果。

/* 3D平移 */
transform: translate3d(50px, 100px, 200px);
transform: translateZ(200px);

/* 3D旋转 */
transform: rotateX(45deg);
transform: rotateY(45deg);
transform: rotateZ(45deg);
transform: rotate3d(1, 1, 1, 45deg);

/* 3D缩放 */
transform: scale3d(2, 1, 0.5);
transform: scaleZ(2);

(四)变换原点

transform-origin属性定义变换的基准点,所有的旋转、缩放等变换都会以这个点为中心进行。可以使用关键字、百分比或具体的像素值来设置。

/* 设置变换的原点 */
transform-origin: center center;
transform-origin: top left;
transform-origin: 50% 50%;
transform-origin: 10px 20px;

(五)组合变换

可以在一个transform属性中同时使用多个变换函数,它们会按照从右到左的顺序依次执行。注意变换的顺序会影响最终的视觉效果。

/* 多个变换函数组合 */
transform: translate(50px, 100px) rotate(45deg) scale(1.2);

(六)变换演示示例

这个综合示例展示了CSS变换的各种效果,包括平移、旋转、缩放、倾斜、组合变换、3D变换、变换原点设置和翻转卡片效果。每个效果都通过悬停触发,让你直观地看到不同变换函数的作用。

  • 完整演示代码:

三、CSS动画(Animation)

(一)什么是动画?

CSS动画通过@keyframes规则定义动画序列,可以创建复杂的动画效果。

(二)@keyframes规则

@keyframes规则是CSS动画的核心,它定义了动画在执行过程中的关键帧。通过指定动画序列中的关键点,浏览器会自动计算并填充这些关键点之间的中间帧,从而创建平滑的动画效果。

  • 基本语法结构

    @keyframes 动画名称 {
      关键帧选择器 {
        CSS属性: 值;
      }
    }
    
  • 关键帧选择器的两种方式

  • 1. 使用百分比(推荐)

    • 0% 表示动画开始时刻
    • 100% 表示动画结束时刻
    • 中间可以设置任意百分比值来定义关键帧
    @keyframes slideIn {
      0% {
        transform: translateX(-100%);
        opacity: 0;
      }
      50% {
        opacity: 0.5;
      }
      100% {
        transform: translateX(0);
        opacity: 1;
      }
    }
    
  • 2. 使用关键字

    • from 等同于 0%
    • to 等同于 100%
    • 适用于简单的两状态动画
    @keyframes fadeInOut {
      from {
        opacity: 0;
      }
      to {
        opacity: 1;
      }
    }
    
  • 关键帧的工作原理

      1. 插值计算:浏览器会自动计算关键帧之间的中间值
      1. 时间分配:根据百分比均匀分配动画时间
      1. 属性变化:只有在关键帧中定义的属性才会发生动画变化
      1. 继承规则:未定义的属性会保持元素的原始值
  • 使用技巧和注意事项

      1. 命名规范:使用有意义的动画名称,如 fadeInslideUpbounce
      1. 关键帧数量:适量的关键帧能创建流畅动画,过多会影响性能
      1. 属性一致性:确保相同属性在所有关键帧中保持一致的单位
      1. 浏览器兼容性:老版本浏览器可能需要厂商前缀 @-webkit-keyframes

(三)animation属性

animation: name duration timing-function delay iteration-count direction fill-mode play-state;
  • 核心属性
    • name: 动画名称(@keyframes定义的名称)
    • duration: 动画持续时间
    • timing-function: 动画的时间函数
    • delay: 动画延迟时间
    • iteration-count: 动画播放次数
    • direction: 动画播放方向
    • fill-mode: 动画填充模式
    • play-state: 动画播放状态

详细属性示例

  • 1. animation-name: 动画名称
    指定要使用的@keyframes动画名称。这个名称必须与@keyframes规则中定义的名称完全匹配,区分大小写。

    animation-name: slideIn;
    
  • 2. animation-duration: 动画持续时间
    设置动画完成一个周期所需的时间。与transition-duration类似,可以使用秒或毫秒作为单位。时间设置要考虑用户体验,过长会让用户感到缓慢,过短可能看不清动画效果。

    animation-duration: 2s;
    
  • 3. animation-timing-function: 时间函数
    控制动画在每个关键帧区间内的速度变化。与transition不同,它作用于每个关键帧之间的过渡,而不是整个动画周期。例如,如果动画有0%、50%、100%三个关键帧,时间函数会分别控制0%-50%50%-100%这两个区间的速度变化。

    • 可以在动画属性中全局设置
    • 也可以在@keyframes规则的具体关键帧中单独设置(会覆盖全局设置),实现更精细的控制。
    /* 全局设置 */
    animation-timing-function: ease-in-out;
    
    /* 在关键帧中单独设置 */
    @keyframes complexMove {
      0% {
        transform: translateX(0);
        animation-timing-function: ease-out; /* 控制0%-50%区间 */
      }
      50% {
        transform: translateX(100px);
        animation-timing-function: ease-in; /* 控制50%-100%区间 */
      }
      100% {
        transform: translateX(200px);
      }
    }
    
  • 4. animation-delay: 延迟时间
    设置动画开始前的等待时间。在创建复杂的动画序列时非常有用,可以让多个元素按顺序开始动画,创造出层次感。

    animation-delay: 0.5s;
    
  • 5. animation-iteration-count: 播放次数
    控制动画重复播放的次数。可以设置具体的数字或使用infinite实现无限循环。需要注意无限循环动画对性能的影响和用户体验。

    animation-iteration-count: 3;      /* 播放3次 */
    animation-iteration-count: infinite; /* 无限循环 */
    
  • 6. animation-direction: 播放方向
    控制动画的播放方向。normal是默认的正向播放,reverse是反向播放,alternate会在正向和反向之间交替,alternate-reverse从反向开始交替。

    animation-direction: normal;    /* 正常方向 */
    animation-direction: reverse;   /* 反向 */
    animation-direction: alternate; /* 交替 */
    animation-direction: alternate-reverse; /* 反向交替 */
    
  • 7. animation-fill-mode: 填充模式
    控制动画在执行前后如何应用样式。none是默认值,动画结束后回到原始状态;forwards保持最后一帧的样式;backwards在延迟期间应用第一帧样式;both同时应用前两者的效果。

    animation-fill-mode: none;      /* 默认 */
    animation-fill-mode: forwards;  /* 保持最后一帧 */
    animation-fill-mode: backwards; /* 应用第一帧 */
    animation-fill-mode: both;      /* 两者都应用 */
    
  • 8. animation-play-state: 播放状态
    控制动画的播放和暂停状态。通常通过JavaScript动态改变这个属性来实现动画的控制,比如在用户交互时暂停或恢复动画。

    animation-play-state: running; /* 播放 */
    animation-play-state: paused;  /* 暂停 */
    

(四)实际应用示例

这个示例演示了三种常见的CSS动画效果:弹跳动画模拟球的弹跳效果,旋转动画创建持续的旋转效果,脉冲动画通过缩放和透明度变化创建呼吸效果。每种动画都使用了不同的@keyframes规则和动画属性。

  • 完整演示代码:

四、性能优化建议

1. 使用transform和opacity

这两个属性不会触发重排(reflow),性能最佳:

/* 推荐 */
.element {
  transform: translateX(100px);
  opacity: 0.5;
}

/* 避免 */
.element {
  left: 100px;
  width: 200px;
}

2. 使用will-change属性

提前告知浏览器元素将要发生变化:

.element {
  will-change: transform, opacity;
}

/* 动画结束后移除 */
.element.animation-finished {
  will-change: auto;
}

3. 使用3D变换触发硬件加速

.element {
  transform: translate3d(0, 0, 0); /* 或 translateZ(0) */
}

4. 避免动画过多元素

同时动画的元素过多会影响性能,考虑分批或延迟执行。

五、实战案例

案例1:卡片悬停效果

这个案例展示了现代网页设计中常见的卡片悬停效果。当鼠标悬停在卡片上时,卡片会向上移动、轻微放大并增强阴影效果,创造出卡片"浮起"的视觉效果。使用了贝塞尔曲线让动画更加自然流畅。

  • 完整演示代码:

案例2:加载动画

这个案例展示了三种不同类型的加载动画:旋转加载器使用边框和旋转动画创建经典的转圈效果;脉冲加载器通过缩放和透明度变化模拟心跳效果;点点加载器使用多个小圆点的错位弹跳动画创建波浪效果。这些都是网页中常用的加载指示器。

  • 完整演示代码:

案例3:页面进入动画

这个案例演示了页面加载时的进入动画效果。四个内容块分别从不同方向进入:从左侧滑入、从右侧滑入、从顶部滑入,以及淡入放大效果。通过设置不同的延迟时间,创造了层次分明的动画序列,让页面内容依次出现,提升用户体验。

  • 完整演示代码:

案例4:按钮点击效果

这个案例展示了四种不同的按钮交互效果:水波纹效果通过伪元素创建点击时的扩散动画;弹跳效果在点击时产生缩放弹跳;脉冲效果使用box-shadow创建向外扩散的脉冲波;旋转效果在悬停和点击时产生旋转动画。这些效果能够为用户提供清晰的交互反馈。

  • 完整演示代码:

六、推荐用法

  • 1. 选择合适的技术

    • 简单的状态变化用transition
    • 复杂的动画序列用animation
    • 几何变换用transform
  • 2. 性能优先

    • 优先使用transformopacity
    • 避免动画widthheight等会触发重排的属性
    • 合理使用will-change
  • 3. 用户体验

    • 动画时长通常在0.2s-0.5s之间
    • 提供动画开关选项
    • 考虑用户的动画偏好设置
  • 4. 浏览器兼容性

    • 使用厂商前缀(-webkit-、-moz-等)
    • 提供降级方案

结语

优秀的动画不仅仅是技术的展示,更是用户体验的重要组成部分。通过掌握这些CSS动画技术,然后不断地实践和优化,相信你将能够创造出既美观又实用的动画效果,为用户带来愉悦的交互体验。

希望这篇文章有帮助到你,如果文章有错误,请你在评论区指出,大家一起进步,谢谢🙏。