Rob*_*low 53 css performance client-side rendering-engine css3
是否值得担心CSS渲染性能?或者我们是否应该完全不用担心CSS的效率而只关注编写优雅或可维护的CSS?
此问题旨在成为前端开发人员的有用资源,其中CSS的某些部分实际上可能会对设备性能产生重大影响,以及哪些设备/浏览器或引擎可能会受到影响.这不是关于如何编写优雅或可维护的CSS的问题,它纯粹是关于性能的(尽管希望这里写的内容可以提供关于最佳实践的更多一般文章).
谷歌和Mozilla已经编写了关于编写高效CSS的指南,CSSLint的规则包括:
避免看起来像正则表达式的选择器.不要使用复杂的相等运算符来避免性能损失
但是他们都没有提供任何证据(我能找到)这些证据的影响.
一个高效的CSS css-tricks.com文章认为(概述效率的最佳做法的负载之后),我们应not .. sacrifice semantics or maintainability for efficient CSS这些天.
一个完美杀死博客文章建议,border-radius并box-shadow呈现数量级比简单的CSS规则慢几个数量级.这在Opera的引擎中非常重要,但在Webkit中却微不足道.此外,粉碎杂志CSS基准测试发现,CSS3显示规则的渲染时间不明显,并且比使用图像渲染等效效果要快得多.
知道你的移动测试各种移动浏览器,并发现他们都快速地(在12毫秒内)渲染CSS3,但看起来他们在PC上进行了测试,因此我们无法推断手持设备如何在CSS3中执行一般.
目前有 很多 的文章如何编写高效的CSS在互联网上.但是,我还没有找到任何全面的证据表明,严重认为CSS实际上会对网站的渲染时间或快速性产生重大影响.
我为这个问题提供了赏金,试图利用SO的社区力量来创建一个有用的,经过深入研究的资源.
Chr*_*ris 48
这里首先想到的是:你正在使用的渲染引擎有多聪明?
这听起来很通用,在质疑CSS渲染/选择的效率时非常重要.例如,假设CSS文件中的第一条规则是:
.class1 {
/*make elements with "class1" look fancy*/
}
Run Code Online (Sandbox Code Playgroud)
因此,当一个非常基本的引擎看到(并且因为这是第一个规则)时,它会查看DOM中的每个元素,并检查每个元素的存在class1.更好的引擎可能会将类名称映射到DOM元素列表,并使用哈希表之类的东西进行高效查找.
.class1.class2 {
/*make elements with both "class1" and "class2" look extra fancy*/
}
Run Code Online (Sandbox Code Playgroud)
我们的示例"基本引擎"将重新访问DOM中的每个元素,以查找这两个类.甲聪明引擎将比较n('class1')和n('class2')其中n(str)是在DOM元素与类的数量str,并采取取其最小值; 假设那是class1,然后传递所有元素,同时class1寻找具有的元素class2.
在任何情况下,现代引擎都很聪明(比上面讨论的例子更聪明),闪亮的新处理器每秒可以完成数百万(数千万)的操作.你的DOM中有数百万个元素是不太可能的,所以任何选择(O(n))的最坏情况性能无论如何也不会太糟糕.
Facebook: ~1900个元素(在我的个人主页上测试).
谷歌:~340个元素(在主页上测试,没有搜索结果).
谷歌: ~950个元素(在搜索结果页面上测试).
雅虎 :~1400个元素(在主页上测试).
Stackoverflow:约680个元素(在问题页面上测试).
AOL: ~1060个元素(在主页上测试).
维基百科: ~6000个元素,其中2420个不是spans或anchors(在维基百科关于Glee的文章中测试过).
Twitter: ~270个元素(在主页上测试).
总结一下,我们得到平均约1500个元素.现在是时候做一些测试了.对于每个测试,我生成1500 divs(在divs某些测试中嵌套在其他测试中),每个测试具有适当的属性,具体取决于测试.
样式和元素都是使用PHP生成的.我已经上传了我使用的PHP,并创建了一个索引,以便其他人可以在本地测试:小链接.
每个测试在三个浏览器上执行5次(报告平均时间):Firefox 15.0(A),Chrome 19.0.1084.1(B),Internet Explorer 8(C):
A B C
1500 class selectors (.classname) 35ms 100ms 35ms
1500 class selectors, more specific (div.classname) 36ms 110ms 37ms
1500 class selectors, even more specific (div div.classname) 40ms 115ms 40ms
1500 id selectors (#id) 35ms 99ms 35ms
1500 id selectors, more specific (div#id) 35ms 105ms 38ms
1500 id selectors, even more specific (div div#id) 40ms 110ms 39ms
1500 class selectors, with attribute (.class[title="ttl"]) 45ms 400ms 2000ms
1500 class selectors, more complex attribute (.class[title~="ttl"]) 45ms 1050ms 2200ms
Run Code Online (Sandbox Code Playgroud)
显然其他人也进行了类似的实验; 这个也有一些有用的统计数据:很少的链接.
假设您正在构建聊天页面,并且您想要设置所有消息的样式.您知道每条消息都div包含一个title并且嵌套在div一个类中.chatpage.这是正确的使用.chatpage div[title]选择的消息,但它也是不好的做法效率明智的.将所有消息赋予类并使用该类选择它们更简单,更易于维护且更高效.
在"是的,这个CSS有意义"的限制范围内的任何事情都可以.
o.v*_*.v. 11
这里的大多数答案都集中在选择器性能上,就好像它是唯一重要的一样.我将尝试覆盖一些精灵琐事(剧透警报:它们并不总是一个好主意),css使用的价值表现和某些属性的渲染.
在我得到答案之前,让我让IMO脱离困境:就个人而言,我强烈不同意所谓的"基于证据的数据"的需求.它只是使性能声明看起来可信,而实际上渲染引擎的领域是异质的,足以使任何这样的统计结论不准确测量并且采用或监视不切实际.
由于原始发现很快就会过时,我宁愿看到前端开发人员对基础原理及其对可维护性/可读性布朗尼点的相对价值有所了解 - 毕竟,过早优化是所有邪恶的根源 ;)
浅,优选一级特定选择器处理更快.原始答案中缺少明确的性能指标,但关键点仍然是:在运行时,HTML文档被解析为包含N平均深度的元素的DOM树,D并且S应用了总共CSS规则.为了降低计算复杂性O(N*D*S),你应该
让最右边的键匹配尽可能少的元素 - 选择器从右到左匹配^用于单个规则资格,因此如果最右键与特定元素不匹配,则无需进一步处理选择器和它被丢弃了.
人们普遍认为*应该避免使用选择器,但应该进一步考虑这一点.实际上,"正常"CSS重置确实匹配大多数元素 - 当这个SO页面被分析时,重置负责所有选择器匹配时间的大约1/3,所以你可能更喜欢normalize.css(仍然,这只会加起来)到3.5ms -反对过早优化的点代表强)
避免使用后代选择器,因为它们需要~D迭代元素.这主要影响不匹配确认 - 例如,正.container .content匹配可能只需要父子关系中元素的一个步骤,但是在html确认否定匹配之前需要遍历DOM树.
最小化DOM元素的数量,因为它们的样式是单独应用的(值得注意的是,这会被浏览器逻辑(例如参考缓存和相同元素的回收样式)所抵消 - 例如,在设置相同的兄弟节点时)
删除未使用的规则,因为浏览器最终必须评估它们对每个呈现元素的适用性.够了 - 最快的规则就是没有那个:)
从渲染引擎性能的角度来看,这些将导致可量化(但是,取决于页面,不一定是可感知的)改进,但是总是存在其他因素,例如流量开销和DOM解析等.
CSS3带来了我们(除其他外)圆角,背景渐变和阴影变化 - 以及它们,一大堆问题.考虑一下,根据定义,预渲染图像的性能优于必须首先渲染的一组CSS3规则.来自webkit wiki:
CSS中的渐变,阴影和其他装饰应仅在必要时使用(例如,当形状基于内容时是动态的) - 否则,静态图像总是更快.
如果这还不够糟糕,可能必须在每次重绘/重排事件时重新计算渐变等(下面有更多详细信息).记住这一点,直到大多数用户用户可以浏览这样的css3重页而没有明显的滞后.
避免高大和宽大的精灵,即使他们的交通占地面积相对较小.通常会忘记渲染引擎无法使用gif/jpg/png,并且在运行时,所有图形资源都使用未压缩的位图进行操作.至少它很容易计算:这个精灵的宽度乘以高度乘以每像素四个字节(RGBA)238*1073*4?1MB.在不同的同时打开的选项卡上的几个元素上使用它,它很快就会产生很大的价值.
在mozilla webdev上已经提到了一个相当极端的情况,但是当使用像对角精灵这样的可疑实践时,这并不是意料之外的.
另一种考虑因素是将各个base64编码的图像直接嵌入到CSS中.
这是一个错误的观念回流只能用JS DOM操作触发-事实上,布局,风格影响的任何应用程序会触发它影响目标元素,其子元素和它后面等,以防止唯一途径不必要的迭代的它是尝试避免渲染依赖项.一个简单的例子是渲染表:
在完全建立布局之前,表通常需要多次传递,因为它们是极少数情况之一,其中元素可以影响在DOM之前的其他元素的显示.想象一下表格末尾的一个单元格,内容非常宽,可以使列完全调整大小.这就是为什么表不会在所有浏览器中逐步呈现的原因.
如果我记得一些错过的重要内容,我会进行编辑.一些完成的链接:
http://perfectionkills.com/profiling-css-for-fun-and-profit-optimization-notes/
http://jacwright.com/476/runtime-performance-with-css3-vs-images/
https://developers.google.com/speed/docs/best-practices/payload
https://trac.webkit.org/wiki/QtWebKitGraphics
https://blog.mozilla.org/webdev/2009/06/22/use-sprites-wisely/
http://dev.opera.com/articles/view/efficient-javascript/
虽然这是真的
10 年前,计算机的速度要慢得多。
如今,您还有更多种类的设备可以访问您的网站。虽然台式机/笔记本电脑突飞猛进,但中低端智能手机市场的设备在许多情况下并不比我们十年前的台式机强大多少。
但话虽如此,在为尽可能广泛的设备范围提供良好体验方面,CSS 选择速度可能接近您需要担心的事情列表的底部。
对此,我无法找到与更现代的浏览器或移动设备相关的特定信息,这些信息与低效的 CSS 选择器有关,但我能够找到以下内容:
http://www.stevesouders.com/blog/2009/03/10/performance-impact-of-css-selectors/
现在相当过时(IE8,Chrome 2),但在某些浏览器中建立各种选择器的效率方面进行了不错的尝试,并尝试量化 CSS 规则的数量如何影响页面渲染时间。
http://www.thebrightlines.com/2010/07/28/css-performance-who-cares/
再次相当过时(IE8,Chrome 6),但在低效的 CSS 选择器中走极端,* * * * * * * * * { background: #ff1; }导致性能下降。