我相信很多前端开发人员都有 基于CSS @keyframes
创建动画的经历。甚至其中有很多人创建了一些很复杂的动效和去实验这个特性。
如果你想要全面了解这篇文章将要介绍的内容,建议你花点时间阅读我 2011年在Smashing Magazine介绍的一个主题 ,这篇文章也是非常不错的。不过,在今天这篇文章中,我并不想介绍有关于CSS动画中所有的属性,我只想专注于CSS动画中的一个属性: animation-fill-mode
属性。
这个动画属性对动画影响并不很明显。例如没有人会对CSS动画中 animation-name
、 animation-duration
等属性感到困惑。但对于 animation-fill-mode
呢?我们接下来通过一些简单的示例来阐述。
你可能知道,一个基于关键帧的动画,它是使用 @keyframes
来定义的。但关键帧它自身并不会做任何事,除非你把关键帧声明好的动画名与元素结合在一下。在CSS中可以通过 animation
这个属性来完成,你可能明白我的意思:
.example { animation: myAnim 2s 500ms 2 normal ease-in forwards; }
当然,上面简写的属性,其扩展出来如下所示:
.example { animation-name: myAnim; animation-duration: 2s; animation-delay: 500ms; animation-iteration-count: 2; animation-direction: normal; animation-timing-function: ease-in; animation-fill-mode: forwards; }
在上面的两个示例中 animation-fill-mode
的属性值都是 forwards
。
再次,即使你从来不使用CSS动画,你也可以轻易的明白上面的声明是什么意思——除了 animation-fill-mode
属性之外。
在 W3C规范 中是这样描述这个属性:
The animation-fill-mode
property defines what values are applied by the animation outside the time it is executing.
继续解释,外面("outside")的执行。具体的说,它能够控制元素在动画执行前与动画完成后时间。言外之意, animation-fill-mode
的值能够它能够控制元素在动画执行前与动画完成后样式。听起来令人非常困惑,但你会明白我的意思。
animation-fill-mode
它能够控制元素在动画执行前与动画完成后的样式。一个带有延迟( animation-delay
),并且按正常方向( animation-direction
)执行的动画(正常方向是指 normal
也就是指动画从 0%
运行到 100%
的动画)。动画按执行时间来划分,它分为三个过程,或者说一次动画过程可以将元素划分为三个状态: 动画等待 、 动画进行 和 动画结束 。默认情况之下,只有在动画进行状态,才会应用 @keyframes
所声明的动画;而在动画等待和动画结束状态,对元素样式并不会产生任何的影响。
接下来观察它的每一个值产生的效果,进一步了解其每个值的定义,当然理解起来可能还会令人有些困惑。
animation-fill-mode
属性可以接受 none
、 forwards
、 backwards
或者 both
四个值中的一个值。接下来分别来解释每个值对其影响。
none
是 animation-fill-mode
的初始值,也是其默认值。如果首先设置了 none
,但想改变其值的话,你需要通过JavaScript来完成或者是通过样式来覆盖。正是这个值,使用得动画不会对动画等待和动画完成的元素样式产生改变。
如果不理解这个值,并不重要,我们可以通过一个示例来加强理解。下面的示例是 animation-fill-mode:none;
的效果:
下图是录制的动画时间轴效果:
你可以看到,在大多数情况下, animation-fill-mode
取值为 none
并不是你想要的东西。记住, 取值为 none
时,使用得动画不会对动画等待和动画完成的元素样式产生改变 。
在这个示例中,开始是一个红色球,然后逐渐变成粉红色,同时向右移动和改变其大小。如果动画结束时,球停止在变小、粉红色、居于右侧,这样效果会更好。这将避免动画一完成就会立马跳回到一开始的位置,避免丑陋的动画效果出现。
接下来的示例,把 animation-fill-mode
的值换成 forwards
。
下图是录制的动画时间轴效果:
现在你可以看到使用 animation-fill-mode:forwards;
的效果。当使用这个值时,告诉浏览器动画结束后,元素的样式将设置为动画的最后一帧的样式。如果我们不需要这种方式,希望元素动画结束之后返回到最初状态之前动画效果,那需要点击重置按钮。
再把 animation-fill-mode
的值改成 backwards
,看看又会发生什么样的变化。
下图是录制的动画时间轴效果:
注意:看到效果了?这个效果和第一个示例的( animation-fill-mode:none;
)是一样的,那这又是为什么呢?
和 forwards
效果不一样,如果设置为 backwards
值,那么在动画等待的那段时间内,元素的样式将设置为动画第一帧的样式。在规范中,对 backwards
是这样描述的:
During the period defined by animation-delay
, the animation will apply the property values defined in the keyframe that will start the first iteration of the animation. These are either the values of the from
keyframe […] or those of the to
keyframe.
为了说明这一点,对上面的DEMO做了两个修改:
from
中给球添加了一个不同的颜色 animation-delay
属性添加了一个延迟播放时间 效果如下:
下图是录制的动画时间轴效果:
现在你看到的效果是,如果你一旦点击播放按钮,球体先会变成一个蓝色。这是因为有一个延迟时间。从技术上讲,每一个动画都有一个默认的延迟时间,只不过这个时间是 0
而以,所以你并没有看到其中的变化。根据前面对 backwards
的描述: 动画等待的那段时间内,元素的样式将设置为动画第一帧的样式 。这样解释你就应该较为明白,因为我们的示例有一个 1s
时间的延迟,这样一来,元素在等待的这 1s
时间内,元素的样式就是关键帧(也就是 @keyframes
中的 frome
或 0%
的样式)第一帧中的样式,在这个示例中,球体变成蓝色。然后在 1s
时间之后,元素动画效果和之前一样。
说实话,我并没有发现 backwards
值有很多实际应用的价值。很难想像在大多数场景动画中,第一帧会有不同的样式风格,而不是在动画前启动前样式。如果你有这方面的实际用例,欢迎分享一下。
最后来看一下 animation-fill-mode
取值为 both
的效果。这个值将会告诉浏览器同时应用 forwards
和 backwards
两个属性值的效果。言外之意, animation-fill-mode
取值为 both
值时, animation-fill-mode
相当于同时配置了 backwards
和 forwards
,意味着在动画等待和动画结束状态,元素将分别应用动画第一帧和最后一帧的样式。
在Demo中操持同样的样式风格,看看示例中取值为 both
时效果会发生什么?
下图是录制的动画时间轴效果:
正如你所见到的,在初始延迟期间,元素样式是动画第一帧样式,然后动画结束之后,元素运用了动画中最后一帧的样式风格。
基于上述介绍以及规范中的一些细节,在使用 animation-fill-mode
时还是需要注意以下几点:
backwards
和 both
两值在最后有一些细小的区别,但这些通过JavaScript或者用户的输入在一些复杂的动画场景中可以派上用场。这些用例可能比比皆是(比如游戏中),但只有实验和创新才能让大家更了解其作用。 animation-direction
设置为 reverse
时将会影响 forwards
和 backwards
效果。如果你把上面的示例做做修改,你将看到它们是如何工作的。 animation-fill-mode
只接受前面描述的四个值,但在 CSS-wide属性值 中有些值也可以使用。 animation-fill-mode
并不是简写属性 animation
中的一部分。 animation
属性中,自定义的动画名不要和 animation-fill-mode
中的值匹配,比如说 forwards
,或者和 animation-direction
的属性值匹配,比如 reverse
。这样浏览器将会把动画名解析为一个 animation-fill-mode
的值能够它能够控制元素在动画执行前与动画完成后样式。听起来令人非常困惑,但你会明白我的意思。 我希望这篇文章的总结能更好的帮助你理解这个属性。其实这里面的一些内容也帮助了我更好的理解了它。其实你可以做一些其它的案例来阐述 animation-fill-mode
在独特条件下的效果,可以用来修正这篇文章中的不对之处。
后续我们将结合一些其它示例,把 animation-fill-mode
结合 animation-direction
、 animation-duration
、 animation-delay
在不同取值下产生的不同效果。感兴趣的同学,欢迎后续文章的更新。当然,如果你有相关的经验,欢迎在下面的评论中与我们一起分享。
本文根据 @Louis Lazaris 的《 Understanding the CSS animation-fill-mode Property 》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处: https://www.sitepoint.com/understanding-css-animation-fill-mode-property/ 。
常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《 图解CSS3:核心技术与案例实战 》。