是否值得担心CSS渲染性能?或者我们是否应该完全不用担心CSS的效率而只关注编写优雅或可维护的CSS?
此问题旨在成为前端开发人员的有用资源,其中CSS的某些部分实际上可能会对设备性能产生重大影响,以及哪些设备/浏览器或引擎可能会受到影响。这不是关于如何编写优雅或可维护的CSS的问题,它纯粹是关于性能的(尽管希望这里写的内容可以提供关于最佳实践的更多一般文章)。
Google和Mozilla撰写了关于编写高效CSS的指南,CSSLint's set of rules包括:
避免看起来像正则表达式的选择器。不要使用复杂的相等运算符来避免性能损失
但是他们都没有提供任何证据(我能找到)这些证据的影响。
css-tricks.com article on efficient CSS认为(在概述了一系列效率最佳实践之后)我们应该这些天来not .. sacrifice semantics or maintainability for efficient CSS
。
一个perfection kills blog post认为border-radius
和box-shadow
比简单的CSS规则慢几个数量级。这在Opera的引擎中非常重要,但在Webkit中却微不足道。此外,smashing magazine CSS benchmark发现CSS3显示规则的渲染时间不明显,并且比使用图像渲染等效效果要快得多。
知道你的移动tested various mobile browsers并发现他们都快速地渲染了CSS3(在12ms内),但看起来他们在PC上进行了测试,因此我们无法推断任何关于手持设备如何使用CSS3执行的一般操作。
有关如何编写高效CSS的互联网上有are many articles。但是,我还没有找到任何全面的证据表明,严重认为CSS实际上会对网站的渲染时间或快速性产生重大影响。
我为这个问题提供了赏金,试图利用SO的社区力量来创建一个有用的,经过深入研究的资源。
这里首先想到的是:你使用的rendering engine有多聪明?
这听起来很通用,在质疑CSS渲染/选择的效率时非常重要。例如,假设CSS文件中的第一条规则是:
.class1 {
/*make elements with "class1" look fancy*/
}
因此,当一个非常基本的引擎看到(并且因为这是第一个规则)时,它会查看DOM中的每个元素,并检查每个元素中是否存在class1
。更好的引擎可能会将类名称映射到DOM元素列表,并使用哈希表之类的东西进行高效查找。
.class1.class2 {
/*make elements with both "class1" and "class2" look extra fancy*/
}
我们的示例“基本引擎”将重新访问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
(在Wikipedia article about Glee上测试过)。
Twitter:~270个元素(在主页上测试)。
总结一下,我们得到平均约1500个元素。现在是时候做一些测试了。对于每个测试,我生成了1500个divs
(嵌套在其他一些divs
中用于某些测试),每个测试具有适当的属性。
样式和元素都是使用PHP生成的。我已经上传了我使用的PHP,并创建了一个索引,以便其他人可以在本地测试:little link。
每个测试在三个浏览器上执行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
显然其他人也进行了类似的实验;这个也有一些有用的统计数据:little link。
假设您正在构建聊天页面,并且您想要设置所有消息的样式。你知道每条消息都在div
中,它有一个title
,并且嵌套在一个带有div
类的.chatpage
中。使用.chatpage div[title]
来选择消息是正确的,但在效率方面也是不好的做法。将所有消息赋予类并使用该类选择它们更简单,更易于维护且更高效。
在“是的,这个CSS有意义”的限制范围内的任何事情都可以。
这里的大多数答案都集中在选择器性能上,就好像它是唯一重要的一样。我将尝试覆盖一些精灵琐事(剧透警报:它们并不总是一个好主意),css使用的价值表现和某些属性的渲染。
在我得到答案之前,让我让IMO脱离困境:就个人而言,我强烈不同意所谓的“基于证据的数据”的需求。它只是使性能声明看起来可信,而实际上渲染引擎的领域是异质的,足以使任何这样的统计结论不准确测量并且采用或监视不切实际。
由于原始发现很快就会过时,我宁愿看到前端开发人员对基础原理及其对可维护性/可读性布朗尼点的相对价值有所了解 - 毕竟,过早优化是所有邪恶的根源;)
Shallow, preferably one-level, specific selectors are processed faster.原始答案中缺少明确的性能指标,但关键点仍然是:在运行时,HTML文档被解析为包含N
元素的DOM树,平均深度为D
,并且总共应用了S
CSS规则。为了降低计算复杂性O(N*D*S)
,你应该
*
选择器,但这一点应该进一步考虑。事实上,“正常”CSS重置确实匹配大多数元素 - 当这个SO页面被分析时,重置约占所有选择器匹配时间的1/3,所以你可能更喜欢normalize.css(仍然,这只能加起来3.5 ms - 反对过早优化的观点很强烈)~D
元素。这主要影响不匹配确认 - 例如,积极的.container .content
匹配可能只需要父子关系中元素的一步,但是在确认否定匹配之前,需要遍历DOM树到html
。从渲染引擎性能的角度来看,这些将导致可量化(但是,取决于页面,不一定是可感知的)改进,但是总是存在其他因素,例如流量开销和DOM解析等。
CSS3带来了我们(除其他外)圆角,背景渐变和阴影变化 - 以及它们,一大堆问题。考虑一下,根据定义,预渲染图像的性能优于必须首先渲染的一组CSS3规则。来自webkit wiki:
CSS中的渐变,阴影和其他装饰应仅在必要时使用(例如,当形状基于内容时是动态的) - 否则,静态图像总是更快。
如果这还不够糟糕,可能必须在每次重绘/重排事件时重新计算渐变等(下面有更多详细信息)。记住这一点,直到大多数用户可以浏览a css3-heavy page like this而没有明显的滞后。
避免高大和宽大的精灵,即使他们的交通占地面积相对较小。通常会忘记渲染引擎无法使用gif / jpg / png,并且在运行时所有图形资源都使用未压缩的位图进行操作。至少它很容易计算:this sprite的宽度乘以高度乘以每像素四个字节(RGBA)是238*1073*4≅1MB
。在不同的同时打开的选项卡上的几个元素上使用它,它很快就会产生很大的价值。
一个相当极端的情况有been picked up on mozilla webdev,但当使用像diagonal sprites这样的可疑实践时,这并不是意料之外的。
另一种考虑因素是将各个base64编码的图像直接嵌入到CSS中。
这是一个误解,reflow只能用JS DOM操作触发 - 事实上,任何影响布局的样式的应用都会触发它影响目标元素,它的子元素和跟随它的元素等。防止不必要的迭代的唯一方法它是尝试避免渲染依赖项。一个简单的例子就是rendering tables:
在布局完全建立之前,表通常需要多次传递,因为它们是极少数情况之一,其中元素可以影响在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/
虽然这是真的
计算机在10年前变慢了。
如今,您还可以使用更多种类的设备访问您的网站。虽然台式机/笔记本电脑实现了跨越式发展,但在中端和低端智能手机市场中,这些设备在很多情况下并没有十年前在台式机中的功能强大得多。
但是,已经说过CSS选择速度可能接近你需要担心的事情列表的底部,以便在尽可能广泛的设备范围内提供良好的体验。
扩展到这一点,我无法找到与更现代的浏览器或移动设备有关的低效CSS选择器的具体信息,但我能够找到以下内容:
* * * * * * * * * { background: #ff1; }
中出现极端情况以确定性能下降。对于这么大的赏金,我愿意冒这个Null的答案:没有正式的CSS选择器会导致渲染中任何明显的减速,并且(在快速计算机和快速浏览器迭代的这一天)发现任何快速的由浏览器制造商解决。即使在移动浏览器中也没有问题,除非粗心的开发人员愿意使用非标准的jQuery选择器。这些被jQuery开发人员标记为冒险,并且确实存在问题。
在这种情况下,缺乏证据证明缺乏问题。因此,使用语义标记(尤其是OOCSS),并报告在不明显的浏览器中使用标准CSS选择器时发现的任何减速。
来自未来的人:2012年的CSS性能问题已经成为过去。
不是css一种无关紧要的方式让它更快,它一定是你看性能时最后看到的东西。以适合您的方式制作您的CSS,编译它。然后把它放在头上。这可能很粗糙,但是当您查看浏览器性能时,需要查看其他内容。如果你在数字办公室工作,你将无法获得额外1ms的加载时间。
正如我评论使用pagespeed for chrome它是一个谷歌工具,分析27个参数的网站css是其中之一。
我的帖子只是关注到,不会有大约99%的网络用户能够打开网站看到它,甚至是IE7等人。比使用css3关闭10%,(如果事实证明你可以额外获得1-10ms的性能)。
大多数人至少有1 mbit / 512 kbit或更高,如果你加载一个沉重的网站,加载大约需要3秒,但你可以节省10毫秒,也许在css?
对于移动设备,您应该为移动设备创建网站,这样当您的设备屏幕尺寸小于“宽度”px时,您就有了一个单独的网站
请在下面评论这是我的观点和我在Web开发方面的个人经验
虽然不直接与代码相关,但使用<link>
而不是@import
来包含样式表可以提供更快的性能。
'Don’t use @import' via stevesouders.com
本文包含了每种类型之间的众多速度测试示例,以及一种类型与另一种类型(例如:通过<link>
调用的CSS文件还包含@import
到另一个css文件)。