第五届CSS大会于2019年3月30日在深圳举办,本次大会由 W3C 联合 w3ctech、前端圈举办。本次会议共邀请了 7 位演讲嘉宾出席演讲,他们分别是CSS排版领域专家陈慧晶,阿里巴巴前端技术专家大漠,css-doodle 作者袁川,《CSS世界》作者、阅文集团前端开发张鑫旭、阿里巴巴高级前端技术专家勾三股四、腾讯CDC高级前端开发陈在真和火狐浏览器工程师、动画领域专家、W3C CSS与SVG工作组成员Brian Birtles


演讲视频


Brian.mp4 (511.52MB)



嘉宾阵容


1122968333.jpg


Brian Birtles 风采


177241305.jpg


185091588.jpg



1256455609.jpg


志愿者合影


1294671756.jpg



主题介绍与PPT下载:


动画可以让你的网站或 app 更加自然、有趣、优美,但动画本身也可能是困难、缓慢、使人不悦的。让我们来一起看看一些浏览器发行者们希望作者们知道的,关于动画常见的误解、不为人知的特性、以及即将到来的技术。


中文版Slide:https://birtles.github.io/cssconf2019/index.zh.html

英文版Slide:https://birtles.github.io/cssconf2019/#/title


演讲内容


大家下午好!非常高兴能来参加这次CSS大会。

我是来自Mozilla的Brian,很抱歉我不能说中文。


动画是我个人最喜欢的一个领域,很高兴和大家分享。今天我分享的主题是:我希望更多人知道的关于 Web 动画的10件事。


我出生在澳大利亚,在东京生活。在Mozilla工作了近15年,主要为Firefox实现动画特性。在此之前我是一个Web开发者,但我想让Web变得更好,所以我开始向Firefox贡献代码。


我也是 W3C 的 SVG 和 CSS 工作组的成员,是 CSS Transitions、CSS Animations 和 Web Animations 标准的编辑。

 

工作之余,我喜欢游泳、冲浪和一切和水有关的事。关于我最喜欢的食物,虽然我也喜欢中国菜,但我更喜欢肉饼(meat pie),当我在大学的时候,经常会花一整天的时间来做肉饼,但是最近,我没有太多的时间来做肉饼,我更多地把精力放在了开发App上。


我做了一个为馅饼爱好者准备的社交 App,今天将用这个App作为例子来介绍动画。


这个 App 有一个类似于 Instagram 的 feed,也有一个饼图。


我从事动画相关工作近15年,还有很多不懂的领域,但有10件事,我非常希望和大家分享。


这10点分为五大类:



这10个要点有的很长,有的很短,前几个要点会很长,后面的要点会越来越短。


第一点是最长、最有挑战性也是最重要的一点。


Transitions


[展示demo:https://birtles.github.io/cssconf2019/index.zh.html#/css-transitions-intro]


如果我们加一个transition,我们能让元素在不同状态之间切换的时候过渡更加平滑。

 

但我们平常不会动画化肉饼,更常见的可能是动画化一个按钮。

[展示demo: https://birtles.github.io/cssconf2019/index.zh.html#/css-transitions-button]

 

在App里,我们可能会动画化一个弹窗。


[展示demo: https://birtles.github.io/cssconf2019/index.zh.html#/css-transitions-overlay-intro]


[展示demo: https://birtles.github.io/cssconf2019/index.zh.html#/css-transitions-overlay-code]


transition很容易使用,估计大家也很常用transition,但可能都会遇到一个问题:在做App时,我用JS添加了一个新元素,想给这个元素加一个transition,但是发现这个元素并没有过渡效果,这是为什么呢?让我们看一看transition是如何工作的。


[展示 https://birtles.github.io/cssconf2019/index.zh.html#/css-transitions-frame-timing]

 

大家都知道浏览器是在固定的时间帧率刷新的

 

通常使用CSS指定宽度,浏览器会自动计算高度


最后会绘制屏幕上的像素


transition更新时候会监测style变动


比如opacity从0变为了1,会有一个transition

 

当我们更新下一帧的时候


浏览器会寻找更新部分

 

有时候就不太灵了


我们该如何解决这个问题?有人可能觉得我们应该再等一帧,或者使用rAF(),但是这并不管用。

 

大家可能会开始抱怨Firefox或者CSS,因为这么简单的transition都无法使用


在Chrome里这也无法使用


在Safari里也许可以使用,可这是Safari的bug


我们来看一看为什么。在这个例子里,我们用了rAF(),但rAF()很特殊,只会在一帧的开始运行,在我们更新样式之前运行,而大部分的JS都在一帧的最后运行。


我们试一试运行两次rAF()看看行不行。


终于可以了!


transition还有一个问题是需要很长时间才能开始


一定有一个更好的办法来解决这个问题


如果我们调用gCS(),让浏览器更新样式,就可以了,这样也会简单一点


使用scrollLeft也可以解决这个问题,但是这会让浏览器重布局,这是没有必要的


大家在使用框架如Vue和React的时候,会经常遇到类似的问题


在使用display: none时也会遇到这种问题,因为display: none的元素没有样式

 

gCS()本身并不会更新样式,在使用gCS()之后还需要使用相关的CSS属性,比如transform


还有一种方法是不使用transition,这也许是更好的方法,我们一会儿将会提到CSS Animations

 

CSS Transitions的另一个需要补充的点


[展示 https://birtles.github.io/cssconf2019/index.zh.html#/css-transitions-hiding]


这个例子的问题是在第二个动画运行的时候


如果元素变成了 display:none、元素被重新创建了、transition-property 属性变了或者元素被移除了,这个transition可能被取消

 

这是另一个类似例子

 

如果我在这个按这个按钮两次


transition可能被取消

 

这是个bug


解决这个问题的一种方法是使用setTimeout,比如你有一个300ms的transition,你可以使用400ms的setTimeout


另一种方法是使用 transitioncancel 事件


还有 transitionrun 事件,这个需要确保一开始是有 transition 的


让我们试试这个


所以大家要注意,transition是可能被取消的


CSS Animations

 

CSS Animations和CSS Transitions不同,使用了@keyframes,将其用到HTML元素上


它有很多的配置属性


回到我们的popup例子,之前我们需要结合rAF()和gCS()才能够让transition运行

 

我们可以用CSS animation优化一下


CSS animation很好,但还是有个问题:easing


我们可以改变动画的easing,比如linear


animation-timing-function: linear;


很多人不知道的是,animation-timing-function也可用于keyframe上

 

很方便也很容易用错


[展示 https://birtles.github.io/cssconf2019/index.zh.html#/css-animations-easing-bug-video]

 

这是个例子


有一天一个同事拿着这个来跟我报bug,问我这个动画是怎么回事,动画中途会变慢,而最后又会变快,Firefox出了问题?


我们来看一下慢动作:


[展示 https://birtles.github.io/cssconf2019/index.zh.html#/css-animations-easing-bug-video-slow-mo]


问题出在哪里了呢?我花了很长时间来找到问题的所在


大家如果看看开发者工具,可以看到一个中途剧变的诡异图形,这是为什么呢?这是animation-timing-function的设计导致的,animation-timing-function只在关键帧之间适用。


解决这个问题的方案就是删除中间的那个keyframe


所以关于CSS Animations,我希望大家知道的要点是animation-timing-function只在关键帧之间适用


那么如果你想对整个动画使用animation-timing-function该怎么办?有时你可以修改关键帧,另一个解决方案是使用Web Animations。也许知道Web Animations的开发者不多,这是个浏览器里的JS API,可以实现CSS Transitions和CSS Animations实现的效果。


[展示 https://birtles.github.io/cssconf2019/index.zh.html#/web-animations-intro]

 

这是一个达成同样效果的Web Animations代码


为什么我们需要Web Animations?主要的原因是性能。虽然有很多的动画库,但性能都比不上Web Animations。Web Animations将来还能够控制使用CSS创建的动画。

 

Firefox和Chrome支持Web Animations,Safari的技术预览版支持Web Animations,稳定版也很快会支持。大约4%的网页已经开始使用Web Animations。


要点4: 鼓励大家现在开始试着使用Web Animations

 

Web Animations可能有点不一样


[展示 https://birtles.github.io/cssconf2019/index.zh.html#/web-animations-vs-css]


JS程序员不喜欢长名字,所以我们把一些名字缩短了


最大的变化在easing上,CSS transitions/animations的默认easing是ease,而Web Animations的默认ease是linear。


[展示 https://birtles.github.io/cssconf2019/index.zh.html#/web-animations-two-easings]


我之前提到了CSS animations只在关键帧之间适用,而在Web Animations中既可对关键帧之间适用,也可对整个动画适用。


[展示 https://birtles.github.io/cssconf2019/index.zh.html#/web-animations-easings-in-devtools]


如果你打开开发者工具,你会看到CSS animations和Web Animations不一样的easing图。第一个图的中间停了一下,而第二个图没有。

鼓励大家现在开始试着使用Web Animations,不过记得Web Animations和CSS Animations有一些细微的差别。

 

性能


性能可能对大家是个很乏味的问题

 

我今天介绍三个点帮助大家让动画更流畅


第一点:可能的话,只动画化 transform 和 opacity


所有的浏览器对transform和opacity的支持都非常流畅


他们能实现的效果非常丰富:移动、大小变化、转动、3D、淡入淡出、大小变化 + 转动 + 淡入淡出、颜色变化、阴影效果、裂开等

 

阴影效果只需要两个元素实现


裂开效果也只是一个transform

 

在我的App里我用了他们来实现背景的动画


其实Gmail在标签的背景里也使用了类似的方案

 

几年前我参与了一个日本动画项目


[展示 https://birtles.github.io/cssconf2019/index.zh.html#/taketori]


除了文字以外,其余所有的动画都只是transform和opacity,如果你足够有创意,这两个属性可以做的事有很多很多。


第二点:开发者工具

 

[展示 https://birtles.github.io/cssconf2019/index.zh.html#/perf-inspection-devtools]


开发者工具里的闪电标志表示这个动画是被浏览器优化过的,运行在一个独立的线程或进程里


右边那张图里的transform没有被动画化,因为它要和height同步

 

这是Firefox开发者工具的一个特性


Chrome的开发者工具也在实现支持中


第三点:在React或者Vue等框架中

 

有可能它只暴露一个图片元素

 

但如果大家看看DOM上发生的事情


可能突然元素都从DOM里消失了

 

这是一个简单的App,但如果是个复杂应用,哪怕是高性能设备,点一个按钮也可能需要几百毫秒的等待时间

 

如果我们把所有东西都一直放在DOM上呢?可能反应时间会大大缩短,因为浏览器无需重复做很多工作


在理想的世界里,所有元素最好能够一直在DOM上,因为这样动画化会很快,但复杂应用可能不适用,因为那会使DOM里的元素太多。


一个解决方案是在DOM里添加一个占位元素

 

要点8:在页面完全准备好之前试着先准备需要动画化的部分

 

动画体验


1月我的sister来到了东京,我们参加了一个动画艺术展


开始很炫,但大约30分钟之后我们觉得头疼、不舒服,所以只好离开


在开发Web应用时,大型的动画,比如整个页面一起动的动画,或者从页面的一端迅速跳到另一端的动画,会使一些人感到不舒服,所以在很多操作系统中都有减少动画的功能。减少动画的功能不只在Windows和macOS上可以使用,也可以在iOS、Android、Linux上使用。


这个功能现在也在CSS上可用,叫prefers-reduced-motion,Firefox/Chrome/Safari都支持


你可以使用这个特性来禁用大型动画


JS也同样支持:https://birtles.github.io/cssconf2019/index.zh.html#/prefers-reduced-motion-js

 

要点9: 你可以(可能也应该)检查用户是否更喜欢减少动画

 

这就是我希望介绍的Web动画的10个点


大家看到这里只有9个点,我在准备这个讲稿时候时,感觉9个就已经足够了

 

动画的性能永远可以优化,但还有一点同样重要,动画是有趣的

 

所以第10点是:玩得开心!


希望大家用动画实现更多有趣好玩的效果,增加Web的乐趣。感谢大家的支持!JS只能在主线程上运行,可能对动画性能有影响。