哪些CSS选择器或规则可以显着影响现实世界中的前端布局/渲染性能?

问题描述 投票:53回答:6

是否值得担心CSS渲染性能?或者我们是否应该完全不用担心CSS的效率而只关注编写优雅或可维护的CSS?

此问题旨在成为前端开发人员的有用资源,其中CSS的某些部分实际上可能会对设备性能产生重大影响,以及哪些设备/浏览器或引擎可能会受到影响。这不是关于如何编写优雅或可维护的CSS的问题,它纯粹是关于性能的(尽管希望这里写的内容可以提供关于最佳实践的更多一般文章)。

Existing evidence

GoogleMozilla撰写了关于编写高效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-radiusbox-shadow比简单的CSS规则慢几个数量级。这在Opera的引擎中非常重要,但在Webkit中却微不足道。此外,smashing magazine CSS benchmark发现CSS3显示规则的渲染时间不明显,并且比使用图像渲染等效效果要快得多。

知道你的移动tested various mobile browsers并发现他们都快速地渲染了CSS3(在12ms内),但看起来他们在PC上进行了测试,因此我们无法推断任何关于手持设备如何使用CSS3执行的一般操作。

有关如何编写高效CSS的互联网上有are many articles。但是,我还没有找到任何全面的证据表明,严重认为CSS实际上会对网站的渲染时间或快速性产生重大影响。

Background

我为这个问题提供了赏金,试图利用SO的社区力量来创建一个有用的,经过深入研究的资源。

css performance css3 client-side rendering-engine
6个回答
48
投票

这里首先想到的是:你使用的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))的最坏情况都不会太糟糕。


更新:

To get some actual practical illustrative proof, I've decided to do some tests. First of all, to get an idea about how many DOM elements on average we can see in real-world applications, let's take a look at how many elements some popular sites' webpages have:

Facebook:~1900个元素(在我的个人主页上测试)。 谷歌:~340个元素(在主页上测试,没有搜索结果)。 谷歌:~950个元素(在搜索结果页面上测试)。 雅虎!:~1400个元素(在主页上测试)。 Stackoverflow:约680个元素(在问题页面上测试)。 AOL:~1060个元素(在主页上测试)。 维基百科:~6000个元素,其中2420个不是spansanchors(在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


底线:

Unless you care about saving a few milliseconds when rendering (1ms = 0.001s), don't bother give this too much thought. On the other hand, it's good practice to avoid using complex selectors to select large subsets of elements, as that can make some noticeable difference (as we can see from the test results above). All common CSS selectors are reasonably fast in modern browsers.

假设您正在构建聊天页面,并且您想要设置所有消息的样式。你知道每条消息都在div中,它有一个title,并且嵌套在一个带有div类的.chatpage中。使用.chatpage div[title]来选择消息是正确的,但在效率方面也是不好的做法。将所有消息赋予类并使用该类选择它们更简单,更易于维护且更高效。


花哨的单线结论:

在“是的,这个CSS有意义”的限制范围内的任何事情都可以。


11
投票

这里的大多数答案都集中在选择器性能上,就好像它是唯一重要的一样。我将尝试覆盖一些精灵琐事(剧透警报:它们并不总是一个好主意),css使用的价值表现和某些属性的渲染。

在我得到答案之前,让我让IMO脱离困境:就个人而言,我强烈不同意所谓的“基于证据的数据”的需求。它只是使性能声明看起来可信,而实际上渲染引擎的领域是异质的,足以使任何这样的统计结论不准确测量并且采用或监视不切实际。

由于原始发现很快就会过时,我宁愿看到前端开发人员对基础原理及其对可维护性/可读性布朗尼点的相对价值有所了解 - 毕竟,过早优化是所有邪恶的根源;)


让我们从选择器性能开始:

Shallow, preferably one-level, specific selectors are processed faster.原始答案中缺少明确的性能指标,但关键点仍然是:在运行时,HTML文档被解析为包含N元素的DOM树,平均深度为D,并且总共应用了S CSS规则。为了降低计算复杂性O(N*D*S),你应该

  1. 让最右边的键匹配尽可能少的元素 - 选择器匹配右到左^用于个别规则资格,因此如果最右键与特定元素不匹配,则无需进一步处理选择器被丢弃了。 人们普遍认为应避免使用*选择器,但这一点应该进一步考虑。事实上,“正常”CSS重置确实匹配大多数元素 - 当这个SO页面被分析时,重置约占所有选择器匹配时间的1/3,所以你可能更喜欢normalize.css(仍然,这只能加起来3.5 ms - 反对过早优化的观点很强烈)
  2. 避免使用后代选择器,因为它们需要迭代~D元素。这主要影响不匹配确认 - 例如,积极的.container .content匹配可能只需要父子关系中元素的一步,但是在确认否定匹配之前,需要遍历DOM树到html
  3. 最小化DOM元素的数量,因为它们的样式是单独应用的(值得注意的是,这会被浏览器逻辑(例如参考缓存和相同元素的回收样式)所抵消 - 例如,在设置相同的兄弟模型时)
  4. Remove unused rules,因为浏览器最终必须评估它们对渲染的每个元素的适用性。够了 - 最快的规则就是没有那个:)

从渲染引擎性能的角度来看,这些将导致可量化(但是,取决于页面,不一定是可感知的)改进,但是总是存在其他因素,例如流量开销和DOM解析等。


接下来,CSS3属性性能:

CSS3带来了我们(除其他外)圆角,背景渐变和阴影变化 - 以及它们,一大堆问题。考虑一下,根据定义,预渲染图像的性能优于必须首先渲染的一组CSS3规则。来自webkit wiki

CSS中的渐变,阴影和其他装饰应仅在必要时使用(例如,当形状基于内容时是动态的) - 否则,静态图像总是更快。

如果这还不够糟糕,可能必须在每次重绘/重排事件时重新计算渐变等(下面有更多详细信息)。记住这一点,直到大多数用户可以浏览a css3-heavy page like this而没有明显的滞后。


接下来,spriting性能:

避免高大和宽大的精灵,即使他们的交通占地面积相对较小。通常会忘记渲染引擎无法使用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/

http://dev.opera.com/articles/view/efficient-javascript/


4
投票

虽然这是真的

计算机在10年前变慢了。

如今,您还可以使用更多种类的设备访问您的网站。虽然台式机/笔记本电脑实现了跨越式发展,但在中端和低端智能手机市场中,这些设备在很多情况下并没有十年前在台式机中的功能强大得多。

但是,已经说过CSS选择速度可能接近你需要担心的事情列表的底部,以便在尽可能广泛的设备范围内提供良好的体验。

扩展到这一点,我无法找到与更现代的浏览器或移动设备有关的低效CSS选择器的具体信息,但我能够找到以下内容:

  1. http://www.stevesouders.com/blog/2009/03/10/performance-impact-of-css-selectors/ 现在相当过时(IE8,Chrome 2),但在某些浏览器中尝试建立各种选择器的效率,并试图量化CSS规则如何影响页面渲染时间。
  2. http://www.thebrightlines.com/2010/07/28/css-performance-who-cares/ 再次过时(IE8,Chrome 6),但在效率低下的CSS选择器* * * * * * * * * { background: #ff1; }中出现极端情况以确定性能下降。

4
投票

对于这么大的赏金,我愿意冒这个Null的答案:没有正式的CSS选择器会导致渲染中任何明显的减速,并且(在快速计算机和快速浏览器迭代的这一天)发现任何快速的由浏览器制造商解决。即使在移动浏览器中也没有问题,除非粗心的开发人员愿意使用非标准的jQuery选择器。这些被jQuery开发人员标记为冒险,并且确实存在问题。

在这种情况下,缺乏证据证明缺乏问题。因此,使用语义标记(尤其是OOCSS),并报告在不明显的浏览器中使用标准CSS选择器时发现的任何减速。

来自未来的人:2012年的CSS性能问题已经成为过去。


1
投票

不是css一种无关紧要的方式让它更快,它一定是你看性能时最后看到的东西。以适合您的方式制作您的CSS,编译它。然后把它放在头上。这可能很粗糙,但是当您查看浏览器性能时,需要查看其他内容。如果你在数字办公室工作,你将无法获得额外1ms的加载时间。

正如我评论使用pagespeed for chrome它是一个谷歌工具,分析27个参数的网站css是其中之一。

我的帖子只是关注到,不会有大约99%的网络用户能够打开网站看到它,甚至是IE7等人。比使用css3关闭10%,(如果事实证明你可以额外获得1-10ms的性能)。

大多数人至少有1 mbit / 512 kbit或更高,如果你加载一个沉重的网站,加载大约需要3秒,但你可以节省10毫秒,也许在css?

对于移动设备,您应该为移动设备创建网站,这样当您的设备屏幕尺寸小于“宽度”px时,您就有了一个单独的网站

请在下面评论这是我的观点和我在Web开发方面的个人经验


0
投票

虽然不直接与代码相关,但使用<link>而不是@import来包含样式表可以提供更快的性能。

'Don’t use @import' via stevesouders.com

本文包含了每种类型之间的众多速度测试示例,以及一种类型与另一种类型(例如:通过<link>调用的CSS文件还包含@import到另一个css文件)。

© www.soinside.com 2019 - 2024. All rights reserved.