CSS3的演进之一是能够定义过渡和动画。多年来前端开发人员一直在寻求不用JavaScript或者Flash而直接使用HTML和CSS来设计交互效果。现在他们终于可以如愿以偿了。

用CSS3过渡,可以在元素状态发生改变的时候改变元素的外观和行为,比如,当鼠标滑过元素,当元素获得焦点,当元素被激活,或者当元素被URL作为目标时。

CSS3中的动画允许用多个关键帧改变一个元素的外观和行为。过渡是让元素从一个状态变化到另一个状态,而动画可以根据不同地关键帧设置多点的过渡。

过渡

正如上面提到的,为了触发一个过渡(transition),一个元素必须要有状态的改变,并且必须为每一个状态定义不同的样式。为不同的状态定义样式最简单的途径是使用:hover, :focus, :active和:target伪类。

总共有4个与过渡相关的属性,包括过渡属性(transition-property),过渡时长(transition-duration),过渡类型(transition-timing-function)和过渡延迟(transition-delay)。想创建一个过渡并不都需要上面所有的属性,最常用的是前三个。

下面的例子中,Box的背景色会在1秒的时间以线性(linear)的方式过渡。

.box {
  background: #8ec63f;
  transition-property: background;
  transition-duration: 1s;
  transition-timing-function: linear;
}
.box:hover {
  background: #f7941d;
}

过渡演示

See the Pen Transition Property by Shay Howe (@shayhowe) on CodePen.

 

浏览器前缀

 

上面的代码就像本节其他代码示例一样没有浏览器前缀。我们故意这样做的目的是为了让代码段看上去简洁和易于理解。但是为了做到最好的跨浏览器支持,应该使用浏览器前缀。

 

你可以参考下面的例子给之前的代码加上前缀。

 

.box {
    background: #8ec63f;
    -webkit-transition-property: background;
       -moz-transition-property: background;
         -o-transition-property: background;
            transition-property: background;
    -webkit-transition-duration: 1s;
       -moz-transition-duration: 1s;
         -o-transition-duration: 1s;
            transition-duration: 1s;
    -webkit-transition-timing-function: linear;
       -moz-transition-timing-function: linear;
         -o-transition-timing-function: linear;
            transition-timing-function: linear;
}
.box:hover {
  background: #f7941d;
}

 

过渡属性

 

transition-property属性决定了哪些元素属性会发生过渡。默认伴随着元素状态的改变,这个元素在该状态中涉及的所有属性将都会被改变。但是,只有transition-property定义了的才会有过渡效果。

 

在上面的例子中,background属性被定义为transition-property的值。因此,只有background这一个属性在1秒的时间以线性(linear)的方式过渡。任何在元素状态中定义而没有作为transition-property的值的属性,都不会有transition-duration和transition-timing-function属性所定义的过渡效果。

 

如果需要为元素的多个属性定义过渡,可以在transition-property属性值中用逗号分隔开。此外,可以使用关键字“all”来设置一个元素的所有属性过渡。

 

.box {
    background: #8ec63f;
    border-radius: 6px
    transition-property: background, border-radius;
    transition-duration: 1s;
    transition-timing-function: linear;
  }
  .box:hover {
    background: #f7941d;
    border-radius: 50%;
  }

过渡属性演示

See the Pen Transition Property by Shay Howe (@shayhowe) on CodePen.

可过渡的元素属性

注意!不是所有的属性都可以过渡,仅仅是那些可定义中间值的属性。如颜色、字体大小等可以从一个值过渡到另一个值,在这两个值之间有可识别的中间值。如display属性因为没有任何中间值所以不能过渡。以下是一些常用的可过渡的元素属性。

过渡时长

我们用transition-duration属性来设置一个过渡效果所持续的时间。这个属性的值可以是秒(s)或毫秒(s)。这些值也可以是小数,比如 .2s。

当元素有多个属性参与过渡的时候你可以为每个属性设置过渡时长。像transition-property属性值一样,你可以用逗号分隔来定义多个过渡时长。这些时长的顺序应该和过渡属性中的定义的值是一一对应的。比如,在transition-property中定义的第一个属性值和transition-duration中第一个时长值匹配,以此类推。

如果设置了多个过渡属性,而只声明了一个过渡时长值,那么所有的过渡属性都将以这一个时长值过渡。

.box {
  background: #8ec63f;
  border-radius: 6px;
  transition-property: background, border-radius;
  transition-duration: .2s, 1s;
  transition-timing-function: linear;
}
.box:hover {
  background: #f7941d;
  border-radius: 50%;
}

过渡时长演示

See the Pen Transition Duration by Shay Howe (@shayhowe) on CodePen.

 

过渡类型

 

transition-timing-function属性是用来设置过渡的缓动速度的。我们已经知道多个过渡属性可以对应一个过渡时长,所以,与多个过渡属性匹配的多个过渡类型也可以只对应一个过渡时长。常用的transition-timing-function属性值包括linear, ease-in, ease-out和ease-in-out。

 

关键字linear定义了一个以恒定速度从一个状态到另一个状态的过渡。ease-in是由慢到快地过渡。而ease-out则是由快到慢地过渡。ease-in-out是开始时速度快,中间加速,最后在过渡结束前减速,即由慢到快再到慢地过渡。

 

每一个过渡类型实质上都是一个三次贝赛尔曲线,我们也可以用函数cubic-bazier(x1,x2,y1,y2)来具体设置这个值。此外,过渡类型的值还包括step-start, step-end,也可以用函数steps(步数,方向)来定义。(译注:关于transition-timing-function另外的这些属性值的具体用法可以参阅https://developer.mozilla.org/en-US/docs/CSS/transition-timing-function ,感谢sunnylost的帮助)。

 

当有多个元素属性参与过渡的时候,你也可以定义多个过渡类型。过渡类型的值和过渡属性的值一样可以用逗号分隔。

 

.box {
  background: #8ec63f;
  border-radius: 6px;
  transition-property: background, border-radius;
  transition-duration: .2s, 1s;
  transition-timing-function: linear, ease-in;
}
.box:hover {
  background: #f7941d;
  border-radius: 50%;
}

 

过渡类型演示

 

See the Pen Transition Timing by Shay Howe (@shayhowe) on CodePen.

过渡延迟

除了可以声明过渡属性,过渡时长,过渡类型之外,你还可以用transition-delay属性设置过渡延迟。过渡延迟是个时间值,可以是秒或毫秒,它用来设置过渡在执行前停滞多长时间。像其他属性一样我们可以设置多个过渡延迟,中间用逗号分隔。

.box {
  background: #8ec63f;
  border-radius: 6px
  transition-property: background, border-radius;
  transition-duration: .2s, 1s;
  transition-timing-function: linear, ease-in;
  transition-delay: 0, 1s;
}
.box:hover {
  background: #f7941d;
  border-radius: 50%;
}

过渡延迟演示

See the Pen Transition Delay by Shay Howe (@shayhowe) on CodePen.

 

过渡复合属性

 

单独声明每一个过渡的属性会让代码看上去密密麻麻的一片,尤其是加上浏览器前缀。幸运的是我们可以通过复合属性transition定义所有不同的属性和属性值。单独使用transition的时候,可以按transtition-property,transition-duration,transition-timing-function,transition-delay的顺序来对应地设置每个属性的值。各个属性值之间用空格分隔。你可以一次定义多组过渡,在每组之间用逗号分隔。

 

.box {
  background: #8ec63f;
  border-radius: 6px;
  transition: background .2s linear, border-radius 1s ease-in 1s;
}
.box:hover {
  color: #f7941d;
  font-size: 18px;
}

 

过渡复合属性演示

 

See the Pen Shorthand Transitions by Shay Howe (@shayhowe) on CodePen.

有过渡效果的按钮

HTML:

<button>Awesome Button</button>

CSS:

button {
  border: 0;
  background: linear-gradient(#768191, #535b65);
  border-radius: 4px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.15), 0 5px 0 #404853;
  color: #fff;
  cursor: pointer;
  font-weight: bold;
  padding: 12px 20px;
  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
  text-transform: uppercase;
  transition: all .1s linear;
}
button:hover {
  color: #d4d7da;
}
button:active {
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.15), 0 2px 0 #404853;
  transform: translateY(3px);
}

 

See the Pen Transitional Button by Shay Howe (@shayhowe) on CodePen.

 

卡片翻转效果

HTML:

 

<div class="card-container">
  <div class="card">
    <div class="side">...</div>
    <div class="side back">...</div>
  </div>
</div>

CSS:

 

.card-container {
  height: 150px;
  perspective: 600;
  position: relative;
  width: 150px;
}
.card {
  height: 100%;
  position: absolute;
  transform-style: preserve-3d;
  transition: all 1s ease-in-out;
  width: 100%;
}
.card:hover {
  transform: rotateY(180deg);
}
.card .side {
  backface-visibility: hidden;
  height: 100%;
  position: absolute;
  width: 100%;
}
.card .back {
  transform: rotateY(180deg);
}

 

See the Pen Card Flip by Shay Howe (@shayhowe) on CodePen.

动画

过渡创建了一种很好的视觉交互,在单状态改变的情况下堪称完美。但是,我们还想控制更多,过渡需要有多个状态的变化,因此,我们用动画来弥补过渡的不足。

动画关键帧

我们使用@keyframes规则来设置一个元素在某个过渡中的多个点。@keyframes规则包括动画名称,动画断点和准备执行动画的元素属性。

@keyframes slide {
  0% {
    left: 0;
    top: 0;
  }
  50% {
    left: 305px;
    top: 100px;
  }
  100% {
    left: 610px;
    top: 0;
  }
}

浏览器前缀的keyframes规则

就像其他的过渡和动画属性一样@keyframes规则必须要加浏览器前缀。浏览器前缀的@keyframes规则看起来像下面这样:

@-moz-keyframes

@-o-keyframes

@-webkit-keyframes

上面例子中定义的动画我们给它命名为slide,直接声明在@keyframes规则开始的地方。我们用百分比来设置不同的关键帧断点,开始是0%,中间是50%,结束是100%。也可以用关键字“from”和“to”来代替0%和100%。除50%之外你还可以附加其他百分比断点。执行动画的元素属性会罗列在每个断点内,上面的例子中是left和top。

注意,和过渡一样,并不是所有的元素属性都可以执行动画,只有个别的元素属性可以被执行动画。如果你想让一个元素从顶端(top)移动到底端(bottom),并且尝试一个从top:0;到bottom:0;的动画,那么它是不会执行的。因为,动画只能把一个过渡效果作用在同一个属性上,而不能从一个属性到另一个属性。

动画关键帧演示

将鼠标悬停在小球上以查看动画效果。

See the Pen Animations Keyframes by Shay Howe (@shayhowe) on CodePen.

 

动画名称

 

我们需要把一个声明了关键帧的动画指定给一个元素。我们可以用@keyframes规则中定义的动画名称作为animation-name的属性值。animation-name声明放在将要执行动画的元素中。

 

.stage:hover .ball {
  animation-name: slide;
}

 

光有animation-name属性还不够,你还需要声明animation-duration属性来让浏览器知道某个动画要用多长时间来完成。

 

动画时长,动画类型和动画延迟

 

除了为一个元素声明animation-name属性外,动画和过渡是类似的,它们都包括时长、类型,如果有必要的话还有延迟时间。首先,动画需要用animation-duration声明一个动画时长。和过渡一样,动画时长可以设置为秒或毫秒。

 

.stage:hover .ball {
  animation-name: slide;
  animation-duration: 2s;
}

 

​我们用animation-timing-function和animation-delay分别声明动画类型和动画延迟。这些属性值的取值和作用效果和前面说到的过渡中的一样。

 

.stage:hover .ball {
  animation-name: slide;
  animation-duration: 2s;
  animation-timing-function: ease-in-out;
  animation-delay: .5s;
}

 

下面这个动画是当鼠标悬停在舞台(stage)上的时候,小球会向左移动并弹跳一次。

HTML:

 

<div class="stage">
  <figure class="ball"></figure>
</div>

CSS:

 

@keyframes slide {
  0% {
    left: 0;
    top: 0;
  }
  50% {
    left: 305px;
    top: 100px;
  }
  100% {
    left: 610px;
    top: 0;
  }
}
.stage {
  height: 150px;
  position: relative;
}
.ball {
    height: 50px;
    position: absolute;
    width: 50px;
}
.stage:hover .ball {
  animation-name: slide;
  animation-duration: 2s;
  animation-timing-function: ease-in-out;
  animation-delay: .5s;
}

 

动画演示

 

将鼠标悬停在小球上以查看动画效果。

 

See the Pen Animation by Shay Howe (@shayhowe) on CodePen.

自定义动画

我们能够通过动画对一个元素的表现效果作进一步自定义,包括指定一个动画的执行次数和动画的方向。

动画循环次数

默认情况下动画只执行一次,就是从开始执行到结尾然后停止。可以使用animation-iteration-count属性来设置动画重复执行的次数。animation-iteration-count属性的值可以是整数或是关键字“infinite”。设置成一个整数时动画会重复执行指定的次数,设置成关键字“indefinite”动画就会一直循环永不停止。

.stage:hover .ball {
  animation-name: slide;
  animation-duration: 2s;
  animation-timing-function: ease-in-out;
  animation-delay: .5s;
  animation-iteration-count: infinite;
}

动画循环次数演示

将鼠标悬停在小球上以查看动画效果。

See the Pen Animation Iteration by Shay Howe (@shayhowe) on CodePen.

 

动画方向

 

除了上面提到的可以设置一个动画的执行次数外,还可以通过声明animation-direction来设置动画完成的方向。animation-direction的属性值包括normal, reverse, alternate和alternate-reverse。

 

normal是让一个动画按预先定义好的从头播放到尾。reverse则是与@keyframes规则中定义的顺序正好相反,从100%开始倒着播放到0%。

 

alternate是让动画先正向播放(forward)再逆向播放(backward)。按着关键帧的定义从0%正向播放到100%,然后从100%再逆向播放到0%。animation-iteration-count的取值会影响到动画正向播放和逆向播放的次数。当动画执行循环中的第一次的时候,它是从0%正向播放到100%,再执行循环中的下一次的时候就是从100%逆向播放到0%。依此类推两次交替执行。alternate也会导致动画类型的反转,例如一个动画是以ease-in的类型从0%播放到100%,然后它就会以ease-out类型从100%播放到0%。

 

alternate-reverse结合了alternate和reverse,让一个动画先逆向播放再正向播放。alternate-reverse开始从100%播放到0%,下次再返回到100%。

 

.stage:hover .ball {
  animation-name: slide;
  animation-duration: 2s;
  animation-timing-function: ease-in-out;
  animation-delay: .5s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

 

动画方向演示

 

将鼠标悬停在小球上以查看动画效果。

 

See the Pen Animation Direction by Shay Howe (@shayhowe) on CodePen.

动画播放状态

animation-play-state属性可以用关键字“running”和“paused ”作为属性值分别设置动画的状态是运动,还是暂停。当你播放一个已经暂停的动画,它会从当前的状态恢复运动而不是再次从头开始。

下面的例子展示的是,当我们通过点击来激活(active)舞台的时候,我们把animation-play-state的值设置为paused。注意动画是如何随即暂停直到你抬起鼠标键。

.stage:hover .ball {
  animation-name: slide;
  animation-duration: 2s;
  animation-timing-function: ease-in-out;
  animation-delay: .5s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}
.stage:active .ball {
  animation-play-state: paused;
}

动画播放状态演示

将鼠标悬停在小球上以查看动画效果。点击暂停动画。

See the Pen Animation Play State by Shay Howe (@shayhowe) on CodePen.

 

动画填充模式

 

animation-fill-mode定义了元素在动画执行之前,之后,或之前和之后的样式效果。animation-fill-mode接受4种值,包括none, forwards, backwards和both。

 

none在动画执行之前和执行之后不会对元素应用任何样式。

 

forwards会让元素在动画完成之后保持最后一个关键帧声明的样式效果。这些样式可能被animation-direction和animation-iteration-count属性值影响而在动画结束时发生变化。

 

backwards会让元素在动画没有开始之前就马上应用第一个关键帧定义的样式效果。即在animation-delay属性所指定的时间内会应用第一个关键帧定义的样式。同样backwards也会受到animation-direction值的影响。

 

both则是让元素在动画开始前应用backwards模式,并且在动画结束后应用forwards模式。

 

(译注:关于animation-fill-mode的相关翻译,我参考了http://technet.microsoft.com/zh-cn/library/hh673530,感兴趣的同学也可以看一下。)

 

.stage:hover .ball {
  animation-name: slide;
  animation-duration: 2s;
  animation-timing-function: ease-in-out;
  animation-delay: .5s;
  animation-fill-mode: forwards;
}
.stage:active .ball {
  animation-play-state: paused;
}

 

动画填充模式演示

 

将鼠标悬停在小球上以查看动画效果。点击暂停动画。

 

See the Pen Animation Fill Mode by Shay Howe (@shayhowe) on CodePen.

动画复合属性

幸运的是动画可以像过渡一样被写在一个复合属性里。可以用一个animation属性代替多个属性的声明。animation属性中属性值的声明顺序应该是animation-name, animation-duration, animation-timing-function, animation-delay, animation-iteration-count, animation-direction,最后是animation-fill-mode。但是,上列属性中最后一个animation-fill-mode不能包括在复合属性的格式里,我们需要单独声明。

.stage:hover .ball {
  animation: slide 2s ease-in-out .5s infinite alternate;
}
.stage:active .ball {
  animation-play-state: paused;
}

动画复合属性演示

将鼠标悬停在小球上以查看动画效果。点击暂停动画。

See the Pen Shorthand Animations by Shay Howe (@shayhowe) on CodePen.

扩展阅读

Understanding CSS3 Transitions via A List Apart

CSS Cubic-Bezier Builder via Rob LaPlaca

The Guide To CSS Animation: Principles and Examples via Smashing Magazine

Using CSS Animations via Mozilla Developer Network

结束!有问题么?

如果你有任何问题请在我的Twitter上随时联系我,同时,如果你觉得本指南不错就请你把它分享给你的朋友们。


特别声明:此文由David根据Shay Howe的英文文章《Transitions & Animations​》进行翻译,目的纯为个人学习所用。如需转载此译文,需注明英文出处:http://learn.shayhowe.com/advanced-html-css/transitions-animations 以及作者相关信息。

英文原文:http://learn.shayhowe.com/advanced-html-css/transitions-animations​

中文译文:http://www.codingserf.com/index.php/2014/02/css3-transitions-animations/