CSS3 transition规范的实际使用经验

        本篇文章主要讲述CSS3 transition规范和在不一样浏览器之间的使用差别,我要谈的是技术背景,主要讨论在使用CSS过渡的过程当中所未预料到的问题。
        结构 (HTML),表现(CSS),以及行为(JavaScript)相分离并非什么新鲜的事情,然而 CSS 能跨越这个界限而且能够在短时间内获得实际的应用,这还真的是一个彻底不一样的讨论话题。

        几周前,我开发一个 JavaScript 模块,在可以使用 CSS 过渡的条件下,JavaScript 端又没法获取到实现过渡的方式。实际遇到的问题是这二者根本没有办法同步,通过屡次的测试后,我只能放弃。而个人测试结果正是本文所讲述的。

        首先,咱们要说一下getcomputedstyle(),是一种用 JavaScript 返回浏览器渲染CSS的属性值的方法。 这个方法能够查看“DOM Level 2: getComputedStyle()”和“CSS Level 2: Computed Values”。

        这对于像 font-size 这样的属性, 经过一个参数即可以转换为像素值。 但对于能够缩写的属性值,例如 margin ,一些浏览器则返回为空。再就是那些同一属性的不一样属性值,例如 font-weight 的值 bold 和700。WebKit也有一个小bug,它会从伪对象中提取出属性值。

        这里所讲述的浏览器之间的差别是2013年1月在使用 Firefox18(Gecko),Opera 12.12 (Presto), Internet Explorer10(Trident),Safari 浏览器6.0.2(WebKit),Chrome 23(WebKit) 以及 Gecko 和 WebKit的 Nightly build channels。


        事不宜迟,让咱们来一块儿看一下规范与实际状况的差别,为了方便,我省略了各浏览器的前缀。在文中我经过建立一个 CSS3 Transitions Test Suite 来发现问题。


一、指定过渡
CSS3 transitions 规范定义了如下四个 CSS 属性:
css

  • transition-propertycss3

  • transition-duration浏览器

  • transition-delay异步

  • transition-timing-function
    编辑器



过渡属性
transition-property 是用来指定当元素其中一个属性改变时执行 transition 效果。系统默认值是 all,这意味着浏览器可以以动画形式呈现全部的可过渡属性(transition-duration持续时间超过0s),该属性支持单个值或以逗号隔开的多个值列表(跟其余全部transition-*属性同样)。

规范规定,一个浏览器应该接受并保存任何它不能识别的属性。所以,下面的例子中将会看到持续2秒的 padding 过渡:ide

  1. <font face="inherit">transition-property:foobar,padding;
    函数

  2. transition-duration:1s,2s;</font>性能

复制代码测试

不一样于规范的是,上面的状况在 WebKit 下会解析为 transition-property: all。 而 Firefox 和 Opera 会解析为 transition-property: all, padding.

过渡持续时间
transition-duration 属性规定了一个过渡从初始状态到目标状态的持续时间。它接受以秒或毫秒的值(例如,2.3S和2300ms都是指2.3秒)。

尽管规范明确规定了过渡值必须为正数,但 Opera 仍接受-5S的值,至少对于getComputedStyle()来讲是这样的。虽然规范中并无限制属性值的大小,但 Opera 和 IE 不接受低于10ms的值。而 WebKit 在 getComputedStyle()执行中有个小bug,例如:返回值0.009999999776482582s会取代0.01s。


过渡延迟时间
transition-delay 属性规定了在执行一个过渡以前的等待时间,一样使用值。Delay 能够是负值,但这会致使动画没法平滑过渡。

IE 和 Opera 不接受 transition-duration 在-10ms和10ms之间的值。WebKit 的 floating point 也会在这儿出现。


transition-timing-function 属性规定了过渡效果的时间曲线。包括cubic-bezier(x1, y1, x2, y2), step(, start|end),和预先定义的 cubic-bezier 曲线关键词,linear, ease, ease-in, ease-out和ease-in-out。在使用 LEA Verou 特有的 cubic-bezier 曲线编辑器时,cubic-bezier 背后的公式就变得再也不重要。尽管 cubic-bezier 曲线会平滑过渡,可是step()函数会在一个固定的间隔跳到下一个值。这样便会产生逐帧动画的效果;如“Pure CSS3 Typing Animation With steps()”。

linear 的计算值一般表示为 cubic-bezier(0, 0, 1, 1)—— WebKit除外。但 WebKit 仍然会返回 cubic-bezier(0.25, 0.1, 0.25, 1),而不是 ease。规范规定 X 值的必须介于0和1之间,y 值能够超过该范围,而WebKit 容许 X 超过此范围,而 Android 浏览器(4.0版本)却混淆了x和y的范围。

2 过渡完成
我前面已经提到了 CSS 过渡异步运行的问题。规范说起了 TransitionEnd 事件容许 JavaScript 与已完成的过渡同步进行。但可恶的是该规范对此并没具体阐述。事实上,它只是简单地说明单个事件会由于已完成过渡的属性而被终止。

规范指出缩写属性(如padding)应为包括其在内的全部属性(padding-top,padding-right,等等)实现过渡,它并无说哪一个属性应该在 TransitionEnd 事件中被具体命名。然而即便过渡被定义为缩写属性(如padding),Gecko,Trident 和 Presto 对于普通书写的子属性(如padding-top)一样能够实现过渡,而 WebKit 则会阻止过渡。 若是你指定 transition-property: padding,WebKit 会为 padding 执行过渡, 但 transition-property: all 这样就会针对 padding-left 执行新的过渡。而当 padding 正执行过渡时, iPhone 6.0.1 的 Safari 浏览器在也能够执行 font-size 和 line-height的过渡。动画

  1. <font face="inherit">.example{padding:1px;transition-property:padding;transition-duration:1s;}

  2. .example:hover{padding:10px;}</font>

复制代码

以上 CSS 将在不一样浏览器下触发不一样的 TransitionEnd:

Gecko,Trident,Presto:
padding-top,padding-right,padding-bottom,padding-left

WebKit:
padding

  1. <font face="inherit">.example {padding: 1px;transition-property: all, padding;transition-duration:1s;}

  2. .example:hover{padding:10px;}</font>

复制代码

以上 CSS 将在不一样浏览器下触发不一样的TransitionEnd:

Gecko,Trident,Presto,WebKit:
padding-top,padding-right,padding-bottom,padding-left

Safari 6.0.1 on iPhone:
padding-top, padding-right, padding-bottom, padding-left, font-size, line-height

你能够指定负值 transition-delay 来“快速实现”转换。可是transition-duration: 1s; transition-delay: -1s; 在 Gecko 和 WebKit 下执行转换并会当即跳转至目标值。而Trident 和 Presto 将不会触发任何事件。

WebKit在 getComputedStyle() 上遇到的浮点问题也一样存在于 TransitionEnd.elapsedTime 中,全部的浏览器如此。 Math.round(event.elapsedTime * 1000) / 1000 可辅助修复。

WebKit 和 IE 浏览器下执行 background-position,会触发对 background-position-x 和 background-position-y 的 TransitionEnd,而不是 background-position 的TransitionEnd。

因此,即便你知道过渡正在执行,你也不能依赖已有的 TransitionEnd.propertyName。尽管你能够编写大量的 JavaScript 来弥补,但在没有对每个属性进行恰当性能检测的状况下,即便你采用最新方法也将没法实现。

3 过渡属性
规范列出了浏览器支持动画过渡的一些CSS属性。固然也包括CSS2.1的属性。还有一些能够动态变化的新属性,如 Flexible Box Layout

该属性数值类型很是重要。margin-top 接受和值,但根据可过渡CSS属性列表,只有是可实现动画效果。但这并不能让浏览器开发商避开值实现过渡。然而,word-spacing 属性除外。该属性包括值,但没有浏览器能以动画形式显示。

撇开 TransitionEnd 事件,若是在过渡发生的指定时间内,getComputedStyle()值从A变到B,该属性就会从值A过渡为值B。若是没有执行,例如“CSS属性值发生变化”,那么也许应该仔细核查下DOM。setTimeout()的解析度还不够好以达到快速过渡(小于几百毫秒的持续时间),这时候requestAnimationFrame()就是你的帮手。在重绘前会提醒你,并提供了一些中间值供参考。除了opera,其余的均可以支持。

相关文章
相关标签/搜索