CSS3之美(十一):过渡与动画

除去 2D、3D变换,CSS3 中最让人兴奋的应该就是过渡与动画模块了。

过渡

CSS2 没有中间状态:当一个属性的值发生改变时,这种改变是突然发生的。

CSS3 引入了过渡模块,提供了改变这种方式的选项。在 CSS 中,过渡就是让一个属性的值从初值逐渐改变至终值。

过渡是隐式的动画,意味着它们只有在 CSS 属性设置了新值的时候才会被触发。为了让过渡产生,必须满足 4个条件:一个初始条件、一个终止条件、过渡本身和触发器。

这里所说的初始条件和终止条件就是指元素的属性发生了变化,有两个状态,一个是初始的属性值,一个是后来的属性值。如果为元素定义了过渡,那么当指定的元素属性发生变化时,过渡就会显现出效果,触发器指的也是指定元素属性与初始态相比发生变化了就能触发过渡。

哪个属性

transition-property 属性指定了元素的哪一个属性(或者多个属性)会有动画效果。它的语法如下:

1
E { transition-property: keyword; }

keyword 默认值是 all,其可以接受的所有值:

  • all
  • none
  • 一个有效的 CSS 属性(并不是所有的 CSS 属性都会有过渡效果)

持续时间

transition-duration 属性定义了过渡从开始到完成的时间长度,其语法是:

1
E { transition-duration: time; }

time 值是一个单位为 ms(毫秒)或者 s(秒)的数字。如果想要出现过渡效果,该属性是必须的,由于其默认值是 0,如果不指明的话就没有过渡效果。

控制过渡过程的速度变化

要控制元素在两种状态之间过渡的方式,我们需要使用 transition-timing-function 属性。该属性能够控制过渡持续期间各个阶段的速度变化。该属性的取值有以下:

  • ease: 默认值,缓慢开始,然后加速,最后缓慢结束
  • linear: 从开始到结束都是同一速度
  • ease-in: 缓慢开始,然后加速直到结束
  • ease-out: 加速开始,缓慢结束
  • ease-in-out: 缓慢开始,中间加速,缓慢结束
  • cubic-bezier(x1, y1, x2, y2): 贝塞尔曲线函数

立方贝塞尔曲线

控制过渡速度变化的属性允许我们使用一个三次贝塞尔曲线函数提供属性值。它的语法如下:

1
E { transition-timing-function: cubic-bezier(x1, y1, x2, y2); }

一条三次贝塞尔曲线是利用四个点绘制出来的,在每条轴线上都是从 0 变化到 1.这四个点已知为 P0、P1、P2、P3,它们定义了线的曲率并使用 (x, y) 坐标进行绘制,其中第一个点 P0 总是在 (0, 0),而最后一个点总是在 (1, 1)。另外两个点定义在函数中,分别是:(x1, y1) 和 (x2, y2)。

线性动画的变化趋势是沿着一条从(0,0)到(1,1)的直线发展的,我们的示例动画会在设置的持续时间内,跟随曲线的发展变化向终点发展。

关键字值 立方贝塞尔曲线
ease 0.25, 0.1, 0.25, 1
linear 0, 0, 1, 1
ease-in 0.42, 0, 1, 1
ease-out 0, 0, 0.58, 1
ease-in-out 0.42, 0, 0.58, 1

过渡开始的时间

transition-delaty 属性设置了过渡开始的时间,其语法如下:

1
E { transition-delay: time; }

transition-duration 一样,time 值是一个单位为 ms 或者 s 的数字。其默认值是 0,意味着过渡会在触发器被触发的时候发生。任何正值都会让过渡在指定的时间长度过去之后才开始,即造成延迟的效果。

我们可以在 transition-delay 上应用负值,会出现有趣的效果,过渡会立即开始,但是会提前跳过负值对应的时间量。过渡看上去就像是从定义的持续时间中间部分开始(持续时间减去延迟时间的绝对值)。

简写属性

过渡的简写属性语法如下:

1
E { transition: transition-property transition-duration transition-timing-function transition-delay; }

多重过渡

我们可以为独立或简写的属性提供一列用逗号隔开的值,轻松地把多种过渡添加到一个元素身上。

1
2
3
4
5
E {
transition-property: border-width, height, padding;
transition-duration: 4s, 500ms, 4s;
}
E { transition: border-width 4s, height 500ms, padding 4s; }

值得注意的是,如果一个独立属性的值比另一个属性更少一些,那么值列表就会被破坏。

1
2
3
4
E {
transition-property: border-width, height, padding;
transition-duration: 4s, 500ms;
}

上面代码中,transition-property 属性有三个值,而 transition-delay 属性却仅仅有两个值,这意味着前者的第三个值(padding)会匹配后者的第一个值(4s)。

动画

过渡虽好,但也有本质上的局限,它们只能够在属性值发生变化时才能应用。CSS3 动画模块超越了过渡模块,它能够使用一种更加灵活的语法,让元素从一种样式逐渐变化到另一种样式,并能够进行更加精细的控制。

@keyframes 规则

创建动画的第一个步骤是定义关键帧。关键帧定义了一个动画从开始到结束的不同时间点的表现。最简单的动画只有两个关键帧——一个在开头,另一个在结尾,更复杂的动画在开头和结尾之间具有多个关键帧。CSS 过渡本质上是一个只有两个关键帧的动画。

在 CSS 中,我们使用 @keyframes 规则声明关键帧,其语法如下:

1
2
3
4
5
@keyframes name {
keyframe {
property: value;
}
}

上面的代码中,

  • name 表示动画的名称,会用与后面动画的调用
  • keyframe 设置了在动画持续期间关键字将要出现的位置,可以使用的值是百分比值或者是 fromto 的其中一个关键字(分别类似于 0% 和 100%)。我们至少需要指定两个关键帧,设置多个时保证每个关键帧在动画中有一个唯一的值就行。

小示例:

1
2
3
4
5
@keyframes example {
from { border-width: 20px; }
50% { border-width: 10px; }
to { border-width: 1px; }
}

动画开始,元素是 10px 边框;动画中途,元素边框为 10px;动画末尾,元素边框 1px。

animation-name 属性

一旦使用了 @keyframes 规则定义了动画,下一个步骤就是添加对动画元素的控制。

animation-name 属性用于指定使用 @keyframes 规则定义的动画名称,以此来调用定义好的动画。

动画持续时间

amimation-duration 属性用于设定动画持续时间,它的语法规则与之前在过渡部分介绍的 transition-duration 属性一样,属性值是一个单位为 s 或者 ms 的数字,默认为 0,但是为 0 动画没有任何效果,负值同理。

注意:如果要想有动画效果,animation-duration 属性必须有,而且其属性值必须为正数。

动画速度变化

animation-timing-function 属性,动画的这个属性与过渡的 transition-timing-function 属性的语法是相同的:

1
E { animation-timing-function: keyword || cubic-bezier(x1, y1, x2, y2); }

该属性可用的关键字值有:

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

动画延迟

animation-delay 属性用于设置动画开始之前的延迟时间,其语法与过渡的延迟时间 transition-delay 属性相同。

属性值是一个单位为 ms 或者 s 的数值,0 意味着动画立即开始,没有延迟,负值可以使动画跳过指定时间。

动画重复

CSS 过渡只能发生一次(或者说两次,如果把相反的过程也算上的话),但是动画不同,动画可以被重复任意次数。动画的重复次数由 animation-iteration 属性设置,其语法如下:

1
E { animation-iteration-count: number || infinite; }

该属性的属性值为一个正整数用于设定动画重复的次数,可能的取值如下:

  • 1: 默认值,
  • infinite: 表示动画无限循环播放
  • 0 或负值: 会阻止动画播放
  • 正整数: 动画会按照播放指定数值的次数

动画播放方向

动画的正常播放是从开始到结束,但它们也可以以相反的方向播放(像过渡那样)。我们可以设置动画是否一直以同一个方向播放,或者交替地向前或向后播放。为了实现这一效果,我们可以使用 animation-direction 属性:

1
E { animation-direction: keyword; }

可使用的属性值关键字值有:

  • normal: 默认值,动画总是从头开始播放到完成
  • reverse: 动画会以相反方向播放
  • alternate: 动画在第奇数次播放时,总是使用 normal 值,即向前播放;动画在第偶数次播放时,总是使用reverse 值,即反方向播放
  • alternate-reverse: 该属性值的作用于 alternate 值相反,奇数的圈动画会向后转,偶数的圈动画向前转。

动画的播放状态

animation-play-state 属性用于指出一个动画是否是活跃的,其语法如下:

1
E { animation-play-state: paused | running; }

该属性有两个关键字值:

  • paused: 表示动画未在播放
  • running: 默认属性值,表示动画正在播放

动画未正在播放时元素的样式

animation-fill-mode 属性用于设置动画没有正在播放时元素的表现,也就说,元素的动画播放前或播放完毕时,元素的表现。

该属性接受以下的关键字值:

  • none: 默认属性值,没有任何样式
  • forwards: 动画开始前或结束后,元素将表现为动画结束时刻的样子
  • backwards: 动画开始前或结束后,元素将表现为动画开始时刻的样子

属性简写

动画简写属性 animation 的语法如下:

1
2
3
4
5
6
7
8
9
10
11
E {
animation:
animation-name
animation-duration
animation-timing-function
animation-delay
animation-iteration-count
animation-direction
animation-fill-mode
animation-play-state
}

我们一个例子来看一下 animation 简写属性与独立属性分开写的对应关系:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@keyframes haha {
/* 在此处声明动画特定帧的行为 */
}
.element {
animation-name: haha;
animation-duration: 2s;
animation-timing-function: ease-out;
animation-delay: 0.5s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-fill-mode: none;
animation-play-state: running;
}
/* 上面的独立属性等价于下面的简写属性 */
.element {
animation:
haha
2s
ease-out
0.5
infinite
alternate
none
running;
}

多重动画

如需为一个元素添加多个动画,使用一个逗号隔开的动画简写属性值列表即可。

支持动画的元素属性

注意!!!并不是所有的元素属性都支持动画特性,MDN 为我们提供了一份清单 a list of CSS properties which can be animated,这上面列出了所有支持 CSS 动画的元素属性。