一、animation 与 transition 比较
-
transition只能定义开始状态和结束状态,不能定义中间状态,也就是说只有两个状态。而动画可以是多个状态间的变化。 -
动画还有一点不同,它可以自动开始。过渡一般需要通过添加样式类或更改状态(如悬停)来触发,但动画可以在页面加载时自动启动。
-
animation更加复杂一些,它允许你按照实际需求添加很多的keyframes来创建动画。它可以自动触发,并且可以循环。
Transitions: A to B

Animations: A to B to C

二、animation 语法介绍
-
给元素添加
animation和添加transition类似。不过它还需要keyframes。并且animation拥有一些transition没有的属性。 -
transition需要指定一个目标属性,例如background或all,animation则需要带keyframes的名字来描述动画。
.element {
animation: ...
}
@keyframes animation-name {
/* Keyframes go here */
}
单独定义keyframes的好处是我们可以复用这些动画。
2.1、基本属性语法介绍
| 属性 | 介绍 |
|---|---|
animation-name |
需要带keyframes的名字来描述动画。 |
animation-duration |
元素动画过程持续时间。例如,1s。 |
animation-timing-function |
元素动画时的速率函数。例如, linear、 ease-in、steps动画分段函数或自定义的 cubic-bezier 函数)。 |
animation-delay |
元素动画延迟的时间。例如,300ms。 |
animation-direction |
设置动画播放方向。normal,reverse,alternate,alternate-reverse |
animation-iteration-count |
这是动画播放的次数。默认情况下,它将播放一次。也可以指定一个数字,或指定 infinite 以使其永久循环。 |
animation-fill-mode |
默认情况下,动画播放完成元素返回其正常状态。使用 animation-fill-mode,我们可以定义元素在动画结束或开始前的状态。 |
animation-play-state |
暂停或恢复动画。值为running或paused,默认为running。可以使用 JavaScript设置此值,控制动画播放状态。 |
2.2、keyframes介绍
keyframes是用来描述动画过程中一系列变化的。
在网页上有一个div 标签,它的背景颜色不断地在变,像下面图中显示的那样:

我们可以用百分比来描述上面的动画:0%的时候蓝色背景,50%的时候橙色,100%的时候绿色。
0% Blue
50% Green
100% Orange
将这些百分比按照keyframes的规则去写并命名。 结果如下:
@keyframes change-background {
0% {
background: blue;
}
50% {
background: green;
}
100% {
background: orange;
}
}
这个动画名字叫 change-background,我们定义开始、中间和结束时的颜色,在这些状态之间变化时,浏览器会自动去计算颜色值的插值。如下图:

下面是一个简写方式,只有两个状态,初始状态和终止状态,与0% 和100%的写法是等价的。
@keyframes name {
from {
...
}
to {
...
}
}
在一行内写好几个百分比数值,这类似一个暂停的效果。下面的 0%, 20% 的意思是,在0% 的时候,元素的 opacity 的值为0,然后保持这个“状态”直到 20%,然后 opacity 开始改变,并在 100% 的时候变为1:
@keyframes name {
0%, 20% {
opacity: 0;
}
100% {
opacity: 1;
}
}
2.3、animation-name属性介绍
animation-name 指的是动画使用的keyframes的名字。例如:
div {
animation: foo 3s linear 1s;
}
@keyframes foo {
...
}
2.4、animation-duration属性介绍
完成一个动画所需的时间。类似于transition-duration ,以秒或毫秒计,如1s 、200ms。
2.5、animation-timing-function属性介绍
这个属性与transition过渡中定时函数属性的值用法基本相同,但效果上会略有不同。在 transition里时间函数(例如ease-out)是作用于整个transition,但animation 里是作用于关键帧之间:

@keyframes foo {
0%{
/ *动画开始时变化速度很快,然后按照ease-out的时间函数,到50%之前越来越慢* /
}
50%{
/ *然后又开始的时候很快,然后慢慢减速至100%的时候* /
}
100%{
/ * 结束 * /
}
}
所以,timing-function 是用在每一个的keyframe,并不是整个的 keyframes。通常在创建关键帧动画时,选择linear会比较好一些,用使用 keyframes控制动画的节奏。我们可以将动画的计时功能定义为 linear,然后在每个关键帧的上控制速度,比较更细粒度的来控制动画:
@keyframes my-animation {
0%{
...
animation-timing-function: linear;
}
50%{
...
animation-timing-function: ease-out;
}
}

在这种情况下,动画的前半部分将是线性的,而后半部分将使用ease-out功能。
2.6、animation-delay属性介绍
animation-delay与transition-delay 类似,此属性表示在开始之前动画的等待时间。如果定义的动画是不断循环的,只有第一次循环前会有等待时间。
animation-delay可以给这个属性一个负值,比如-3s。动画会直接从第3s开始执行,仿佛已经运行过了 3s 一样。比如下面这段CSS:
.box1,.box2 {
width: 300px;
height: 100px;
outline: 2px dashed #000;
animation: change-translateX 6s linear;
}
.box {
animation-delay: -3s;
}
@keyframes change-translateX {
0% {
transform: translateX(0px);
}
50% {
transform: translateX(300px);
}
100% {
transform: translateX(600px);
}
}

上图设置了6s执行完动画,到0%到50%的时候执行了3s,所以当动画延迟3s执行的时候,刚好到transform: translateX(300px)这个阶段。最后3s执行50%到100%的阶段。加上animation-delay: -3s刚好6s。
2.7、animation-direction属性介绍
动画通常从0% 开始,到100%结束。animation-direction使用normal,reverse,alternate 和alternate-reverse来控制动画变化的方向。
animation-direction四个值的介绍:
normal:按顺序播放,也是默认值。 是指从0%开始,到100%结束。reverse:按反方向播放,是指从100%播放(或循环)到0%alternate:动画轮流反复播放,即从0%播放到100%然后再播放到0%。alternate-reverse:指动画轮流反方向反复播放,即从100%播放到0%然后再播放到100%。

2.8、animation-iteration-count属性介绍
动画播放的次数。默认情况下,它将播放一次。也可以指定一个数字,或指定 infinite 以使其永久循环。
2.9、animation-fill-mode属性介绍
animation-fill-mode 使用none,forwards,backwards和both定义元素在动画结束或开始前的状态。animation-fill-mode四个值的介绍:
none:动画播放完成元素返回其正常状态,也是默认值。forwards:表示当动画完成后,元素状态保持最后一个关键帧的值。backwards:有动画延迟时,动画开始前,元素状态保持为第一帧的状态。both:表示forwards和forwards效果都有。

div {
animation: change-translateX 4s linear 1s;
}
@keyframes change-translateX {
0% {
transform: translateX(300px);
}
50% {
transform: translateX(500px);
}
100% {
transform: translateX(700px);
}
}
上图设置元素动画keyframes。当animation-fill-mode为forwards的时候,元素的状态就保持在了最后一个关键帧的值,也就是transform:translateX(700px)。
当animation-fill-mode属性为backwards的时候,设置动画延迟3s后执行,可以看到动画在开始前是处于transform: translateX(300px)处,动画结束后回到0px 处。
当animation-fill-mode属性为both的时候就包含了forwards和forwards的双重效果。
2.10、animation-play-state属性介绍
如果需要暂停或恢复动画,则可以使用此属性执行操作。值为running或paused,默认为 running。可以使用JavaScript设置此值,控制动画播放状态。
div:hover {
animation-play-state: paused;
}

2.11、animation 动画的简写形式
- 如果提供多组属性值,以逗号进行分隔。
- 如果只提供一个
time参数,则为animation-duration的值定义。 - 如果提供二个
time参数,则第一个为animation-duration的值定义,第二个为animation-delay的值定义。
div {
animation-name: foo;
animation-duration: 3s;
animation-timing-function: linear;
animation-delay: 1s;
animation-iteration-count: infinite;
animation-direction: reverse;
animation-fill-mode: forwards;
animation-play-state: pause;
}
div {
animation: foo 3s liner 1s infinite reverse forwards pause;
}
三、摇摆按钮实现

button {
font-size: 20px;
padding: 10px 20px;
background: #3C3C3C;
color: #fff;
border-top: 3px solid orange;
border-radius: 0 0 5px 5px;
}
@keyframes wiggle {
0%,
7% {
transform: rotateZ(0);
}
15% {
transform: rotateZ(-15deg);
}
20% {
transform: rotateZ(10deg);
}
25% {
transform: rotateZ(-10deg);
}
30% {
transform: rotateZ(6deg);
}
35% {
transform: rotateZ(-4deg);
}
40%,
100% {
transform: rotateZ(0);
}
}
</style>
具体旋转和变化的可以看下面的动图,浏览器自动完成了每个关键帧之间的插值。

四、loading动画实现

.load {
display: inline-block;
width: 200px;
height: 200px;
background: orange;
border-radius: 50%;
animation: loading 1s linear infinite;
}
.two {
animation-delay: -0.2s;
}
.three {
animation-delay: -0.4s;
}
@keyframes loading {
0% {
transform: scale(0.3);
opacity: 0.5;
}
50% {
transform: scale(1);
opacity: 1;
}
100% {
transform: scale(0.3);
opacity: 0.5;
}
}
<div class="load"></div>
<div class="load two"></div>
<div class="load three"></div>
loading动画效果主要是利用animation-delay负值的时间差来实现元素同一时间执行动画而元素样式却不一样。
五、参考
cssanimation.rocks/twitter-fav…
cssanimation.rocks/pseudo-elem…