CSS 中的 transform
,transition
和 animation
是分开的三部份内容,其中 transfrom
主要是控制元素变形,并无一个时间控制的概念,而 transition
和 animation
才是动画的部分,它们能够控制在一个时间段里,元素在两个或以上的状态切换的效果。css
基本上咱们会有这样的一个简单的概念,CSS 的动画效果由浏览器控制和渲染,理论上比 JavaScript 的动画效果性能好,可是控制上没有 JavaScript 那么灵活方便。html
迪士尼出版的一本书中说起了动画效果的十二个原则,这篇文章讲解得比较详细,而且将其结合到页面动画中:网页动画的十二原则。css3
transition
容许咱们在 CSS 属性变化时给它添加一个过分的动画效果。一般状况下,CSS 属性变化是当即生效的,新的属性值在超级短的时间内替换掉旧的属性值,而后浏览器从新绘制样式内容(多是 reflow 或者 repaint)。大部分状况下会感受样式变化突兀,而 transition
则能够添加顺滑的一个变化效果。例如:git
.content { background: magenta; transition: background 200ms ease-in 50ms; } .content:hover { background: yellow; transition: background 200ms ease-out 50ms; }
transition
的兼容性,不算差,基本上移动设备均可以使用了,而且能作到渐进加强,支持的便有过渡效果,不支持的即是直接切换,因此能够放心使用。github
CSS 的 transition
有四个属性:web
transition-delay
延迟多久后开始动画算法
transition-duration
过渡动画的一个持续时间chrome
transition-property
执行动画对应的属性,例如 color
,background
等,可使用 all
来指定全部的属性浏览器
transition-timing-function
随着时间推动,动画变化轨迹的计算方式,常见的有:linear,ease,ease-in,ease-out,cubic-bezier(...) 等。详细参考:transition-timing-function,里边有各个效果的简单例子。网络
这四个属性能够简写成为:
.class { transition: <property> <duration> <timing-function> <delay> }
例如前边的那个例子,当 .content
元素 hover 时,50 毫秒后背景颜色从 magenta 渐变到 yellow,持续时间 200 毫秒,使用的是 ease-out 的算法。留意下:transition
生效的是对应的选择器的属性,例如 .content:hover
中的 transition
即是从 .content
的 magenta 到 yellow 过渡效果的控制,而 .content
中的 transition
则是控制不 hover 时,背景颜色从 yellow 到 magenta 的变化过程。
all
这个属性值是这样的,它对应选择器下的元素的全部 CSS 属性生效,不管在哪里声明的 CSS 规则,并不局限于在同个代码块下。
若是须要不一样属性对应不一样的效果,能够这么来写:
.demo { transition-property: all, border-radius, opacity; transition-duration: 1s, 2s, 3s; /* 当这样使用时,确保 all 在第一个,由于若是 all 在后边的话,它的规则会覆盖掉前边的属性 */ }
transition
的 none
属性较少用到,通常用于移除本来有的动画效果。none
无法和逗号一块儿使用来移除特定属性的动画效果,只能直接干掉 transition
,若是要移除特定的属性效果,能够重写 transition
而不把要移除的属性写进去,或者比较 trick 的作法是设置 duration
为 0。
并非全部的 CSS 属性都是能够添加 transition
效果的。详细能够参考文档:animatable properties。可能常常遇到的就是 display
这个属性并不能添加 transition
效果,你能够考虑使用 visibility
或者后边会说起的 animation
。
关于 transition-timing-function
的各个算法的一个变化曲线是怎么样的,咱们可使用 chrome 的开发者工具来看一下,CSS 中你编写了对应的 transition
后,把鼠标移到 transition-timing-function
的那个值前边,以下图:
这样你即可以很清晰地看到这个算法的一个变化轨迹是怎么用的,而后选择符合本身须要的一个算法。
transitionend
事件会在 transition
动画结束的时候触发。一般咱们会在动画结束后执行一些方法,例如继续下一个动画效果或者其余。Zepto.js 中的动画方法都是使用 CSS 动画属性来处理,而其中动画运行后的回调便应该是使用这个事件来处理。
transitionend
事件触发时会传入一些动画相关的参数,例如:propertyName
,elapsedTime
,详细内容能够参考:transitionend。
transition
在不少 UI 框架中是很常见的属性,当咱们开发一个交互效果的时候,从某个状态到达另一个状态时,transition
可使得这个过程变得更加温馨和顺滑。例如上边的 hover
时的背景颜色的切换,控制元素的显示和隐藏时使用 opacity
来实现渐隐渐现。
当 transition
配合上 transform
提供的多样化的元素变化能力后,即可以绘制出不少有趣的交互渐变效果了。最近使用过程当中作的一个简单效果的例子,点击查看。
很常见还有表单 input 报错时边框变红,按钮 hover 时背景渐变等,不少的 CSS 交互效果会由于 transition
变得更加天然。
虽然 transition
已经提供了很棒的动画效果了,可是咱们只可以控制从一个状态到达另一个状态,无法来控制多个状态的不断变化,而 animation
而帮助咱们实现了这一点。使用 animation
的前提是咱们须要先使用 @keyframes
来定义一个动画效果,@keyframes
定义的规则能够用来控制动画过程当中的各个状态的状况,语法大抵是这个样子:
@keyframes W { from { left: 0; top: 0; } to { left: 100%; top: 100%; } }
@keyframes
关键词后跟动画的名字,而后是一个块,块中有动画进度的各个选择器,选择器后的块则依旧是咱们常见的各个 CSS 样式属性。
在这里,控制动画的整个过程的选择器很重要,语法相对简单,你可使用 from
或者 0%
来表示起始状态,而 to
或 100%
来表示结束状态。中间的部分你均可以使用百分比来进行表示。选择器后的块则是在到达这个进度状态时元素的样式应该是怎么样的,整个的过渡动画在这个的控制基础上由浏览器去绘制。
一样地,不是全部的属性均可以有动画效果,MDN 维护了一份 CSS 动画的属性列表 可供参考。
一般来讲,多个状态下的相同属性的值应该是能够取到它们的中间值的,例如 left 从 0% 到 100%,若是无法取到中间值,如 height 从 auto 到 100px,有可能出现奇怪的一些情况,而且不一样浏览器对此的处理也不尽相同,因此请尽可能避免这种状况。
animation
的属性比 transition
多,以下:
animation-name
你须要的动画效果的 @keyframes
的名字。
animation-delay
和 transition-delay
同样,动画延迟的时间。
animtaion-duration
和 transition-duration
同样,动画持续的时间。
animation-direction
动画的一个方向控制。
默认是 normal
,若是是上述的 left 从 0% 到 100%,那么默认是从左到右。若是这个值是 reverse
,那么即是从右到左。
因为 animation
提供了循环的控制,因此还有两个值是 alternate
和 alternate-reverse
,这两个值会在每次循环开始的时候调转动画方向,只不过是起始的方向不一样。
例如仍是 left 的例子,假设设置了 animation-direction: alternate; animation-iteration-count: infinite;
,那么这个元素从左到右移动后,便调转方向,从右到左,如此循环。
animation-fill-mode
这个属性用来控制动画先后,@keyframes
中提供的 CSS 属性如何应用到元素上。
默认值是 none
,还有其余三个选择:forwards
,backwards
,both
。
假设是 none
,那么动画先后,动画中声明的 CSS 属性都不会应用到元素上。即动画效果执行后,元素便恢复正常状态。
若是是 forwards
,那么动画结束后,会把最后状态的 CSS 属性应用到元素上,即保持动画最后的样子。而 backwards
则相反,both
则都会,计算得出最后的一个结果。
animation-timing-function
和 transition-timing-function
同样,动画变化轨迹的算法。
animation-iteration-count
动画循环次数,若是是 infinite
则无限次。有趣的是,支持小数,即 0.5 表示动画执行到一半。
animation-play-state
动画执行的状态,两个值 running
或者 paused
,能够用来控制动画是否执行。
上述这些属性能够简写为:
.class { animation: <duration> <timing-function> <delay> <iteration-count> <direction> <fill-mode> <play-state> <name> }
略长,固然,平时使用中多是省略部分参数的。
记得 CSS 中的层叠概念么,优先级高的属性会覆盖优先级低的属性,当 animation 应用到元素中时,动画运行过程当中,@keyframes
声明的 CSS 属性优先级最高,比行内声明 !important
的样式还要高。如今浏览器的实现是这样子的,可是标准文档中的说法应该是能够被 !important
声明的属性所覆盖。
因为 animation-name
是能够指定多个动画效果的,因此这里便会出现动画的一个顺序问题。后指定的动画会覆盖掉前边的,例如:
#colors { animation-name: red, green, blue; /* 假设这些 keyframe 都是修改 color 这个属性 */ animation-duration: 5s, 4s, 3s; }
上述代码的动画效果会是这样:前 3 秒是 blue,而后接着 1 秒是 green,最后 1 秒是 red。整个覆盖的规则是比较简单的。
若是一个元素的 display
设置为 none
,那么在它或者它的子元素上的动画效果便会中止,而从新设置 display
为可见后,动画效果会从新重头开始执行。
咱们能够经过绑定事件来监听 animation 的几个状态,这些事件分别是:
animationstart 动画开始事件,若是有 delay 属性的话,那么等到动画真正开始再触发,若是是没有 delay,那么当动画效果应用到元素时,这个事件会被触发。
animationend 动画结束的事件,和 transitionend 相似。若是有多个动画,那么这个事件会触发屡次,像上边的例子,这个事件会触发三次。若是 animation-iteration-count
设置为 infinite
,那么这个事件则不会被触发。
animationiteration 动画循环一个生命周期结束的事件,和上一个事件不同的是,这个在每次循环结束一段动画时会触发,而不是整个动画结束时触发。无限循环时,除非 duration 为 0,不然这个事件会无限触发。
animation event 相关的属性能够参考:animationEvent。
animation
能够实现控制在多个状态下进行动画切换,因此应用的场景比 transition
要普遍得多,可使用 animation 实现大量的动效,具体能够查看下 animate.css 这个库。
我上边提到的 简单例子 中也包括了一个简单地使用 animation
来缩放字体,和一个简单进度条的例子。
如今愈来愈多的页面开发是面向移动端,因此咱们会更加关注性能方面的问题。浏览器绘制动画的过程当中,涉及的主要是 Layout,Paint,Composite 的处理,当一个动画触发的浏览器处理越少,影响的区域越少,那么便消耗越低,性能上越好。
咱们能够参考这个 CSS Triggers 网站提供的列表,这里展现了修改属性时对应的浏览器内核所须要作的处理。简单归纳来讲,动画尽可能少涉及布局相关的调整,由于布局上一旦变化,会涉及外部元素和内部元素的位置调整,对浏览器的消耗至关大,而在现代浏览器中,拥有比较好动画性能的属性就是 transform
和 opacity
,建议须要动画的时候多往这两个属性考虑,例如字体要放大,避免使用 font-size
,而是用 transform: scale()
等。
咱们可使用 will-change
来声明即将变化的属性,这可让浏览器提早作一些优化工做,关于这个属性,更多内容能够参考: will-change。值得留意的是,别滥用 will-change
,在太多的元素上使用或者应用太多的属性都会致使浏览器资源浪费。
Chrome 浏览器的开发者工具提供的 Timeline 工具能够帮助咱们来查看页面渲染的一个性能表现状况,以下图:
Timeline 能够用来获取脚本执行性能,网络请求性能等的表现数据,可是这里咱们只是关于动画渲染,因此只是勾选了 paint。咱们能够看到渲染能够保持在 60 FPS,便不会感受到卡顿。当渲染 FPS 太低的时候,图示那里会出现红色的提示,经过这个工具能够帮助咱们在须要的时候作针对性的优化。
对于 CSS 动画性能上的东西,本人还比较缺少实践经验,最近 w3cplus 上出现了大量的关于 CSS 动画性能相关的文章,有兴趣能够查阅。