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

时间:2022-05-15 15:45:17

Is it worth worrying about CSS rendering performance? Or should we just not worry about efficiency at all with CSS and just focus on writing elegant or maintainable CSS instead?

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

This question is intended to be a useful resource for front-end developers on which parts of CSS can actually have a significant impact on device performance, and which devices / browsers or engines may be affected. This is not a question about how to write elegant or maintainable CSS, it's purely about performance (although hopefully what's written here can inform more general articles on best-practice).

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

Existing evidence

Google and Mozilla have written guidelines on writing efficient CSS and CSSLint's set of rules includes:

Google和Mozilla编写了有关编写高效CSS的指南,CSSLint的规则包括:

Avoid selectors that look like regular expressions .. don't use the complex equality operators to avoid performance penalties

避免看起来像正则表达式的选择器。不要使用复杂的相等运算符来避免性能损失

but none of them provide any evidence (that I could find) of the impact these have.

但是他们都没有提供任何证据(我能找到)这些证据的影响。

A css-tricks.com article on efficient CSS argues (after outlining a load of efficiency best practices) that we should not .. sacrifice semantics or maintainability for efficient CSS these days.

关于高效CSS的css-tricks.com文章认为(在概述了一系列效率最佳实践之后)我们不应该牺牲高效CSS的语义或可维护性。

A perfection kills blog post suggested that border-radius and box-shadow rendered orders of magnitude slower than simpler CSS rules. This was hugely significant in Opera's engine, but insignificant in Webkit. Further, a smashing magazine CSS benchmark found that rendering time for CSS3 display rules was insignificant and significantly faster than rendering the equivalent effect using images.

完美杀死博客文章表明,边界半径和盒子阴影比简单的CSS规则慢几个数量级。这在Opera的引擎中非常重要,但在Webkit中却微不足道。此外,粉碎杂志CSS基准测试发现,CSS3显示规则的渲染时间无关紧要,并且比使用图像渲染等效效果要快得多。

Know your mobile tested various mobile browsers and found that they all rendered CSS3 equally insignificantly fast (in 12ms) but it looks like they did the tests on a PC, so we can't infer anything about how hand-held devices perform with CSS3 in general.

知道你的移动测试各种移动浏览器,发现他们都快速地(在12毫秒内)渲染了CSS3,但看起来他们在PC上进行了测试,所以我们无法推断任何关于手持设备如何使用CSS3进行测试一般。

There are many articles on the internet on how to write efficient CSS. However, I have yet to find any comprehensive evidence that badly considered CSS actually has a significant impact on the rendering time or snappiness of a site.

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

Background

stand back, I'm going to try science http://brightgreenscotland.org/wp-content/uploads/2010/09/stand-back-Im-going-to-try-science.png

退后一步,我将尝试科学http://brightgreenscotland.org/wp-content/uploads/2010/09/stand-back-Im-going-to-try-science.png

I offered bounty for this question to try to use the community power of SO to create a useful well-researched resource.

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

6 个解决方案

#1


48  

The first thing that comes to mind here is: how clever is the rendering engine you're using?

这里首先想到的是:你正在使用的渲染引擎有多聪明?

That, generic as it sounds, matters a lot when questioning the efficiency of CSS rendering/selection. For instance, suppose the first rule in your CSS file is:

在质疑CSS渲染/选择的效率时,这听起来很通用。例如,假设CSS文件中的第一条规则是:

.class1 {
    /*make elements with "class1" look fancy*/
}

So when a very basic engine sees that (and since this is the first rule), it goes and looks at every element in your DOM, and checks for the existence of class1 in each. Better engines probably map classnames to a list of DOM elements, and use something like a hashtable for efficient lookup.

因此,当一个非常基本的引擎看到(并且因为这是第一个规则)时,它会查看DOM中的每个元素,并检查每个元素中是否存在class1。更好的引擎可能会将类名称映射到DOM元素列表,并使用哈希表之类的东西进行高效查找。

.class1.class2 {
    /*make elements with both "class1" and "class2" look extra fancy*/
}

Our example "basic engine" would go and revisit each element in DOM looking for both classes. A cleverer engine will compare n('class1') and n('class2') where n(str) is number of elements in DOM with the class str, and takes whichever is minimum; suppose that's class1, then passes on all elements with class1 looking for elements that have class2 as well.

我们的示例“基本引擎”将重新访问DOM中的每个元素,以查找这两个类。一个聪明的引擎将比较n('class1')和n('class2'),其中n(str)是DOM中的元素数与str类,并取最小值;假设是class1,然后传递class1的所有元素,同时查找具有class2的元素。

In any case, modern engines are clever (way more clever than the discussed example above), and shiny new processors can do millions (tens of millions) of operations a second. It's quite unlikely that you have millions of elements in your DOM, so the worst-case performance for any selection (O(n)) won't be too bad anyhow.

在任何情况下,现代引擎都很聪明(比上面讨论的例子更聪明),闪亮的新处理器每秒可以进行数百万(数千万)次操作。你的DOM中有数百万个元素是不太可能的,因此无论如何,任何选择(O(n))的最坏情况都不会太糟糕。


Update:

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 elements (tested on my personal main page).
Google: ~340 elements (tested on the main page, no search results).
Google: ~950 elements (tested on a search result page).
Yahoo!: ~1400 elements (tested on the main page).
*: ~680 elements (tested on a question page).
AOL: ~1060 elements (tested on the main page).
Wikipedia: ~6000 elements, 2420 of which aren't spans or anchors (Tested on the Wikipedia article about Glee).
Twitter: ~270 elements (tested on the main page).

Facebook:约1900个元素(在我的个人主页上测试)。谷歌:~340个元素(在主页上测试,没有搜索结果)。谷歌:~950个元素(在搜索结果页面上测试)。雅虎!:~1400个元素(在主页上测试)。 *:约680个元素(在问题页面上测试)。 AOL:~1060个元素(在主页上测试)。*:~6000个元素,其中2420个不是跨度或锚点(在*关于Glee的文章中测试过)。 Twitter:~270个元素(在主页上测试)。

Summing those up, we get an average of ~1500 elements. Now it's time to do some testing. For each test, I generated 1500 divs (nested within some other divs for some tests), each with appropriate attributes depending on the test.

总结一下,我们得到平均约1500个元素。现在是时候做一些测试了。对于每个测试,我生成了1500个div(嵌套在一些其他div中用于某些测试),每个div都具有适当的属性,具体取决于测试。


The tests

The styles and elements are all generated using PHP. I've uploaded the PHPs I used, and created an index, so that others can test locally: little link.

样式和元素都是使用PHP生成的。我已经上传了我使用的PHP,并创建了一个索引,以便其他人可以在本地测试:小链接。


Results:

Each test is performed 5 times on three browsers (the average time is reported): Firefox 15.0 (A), Chrome 19.0.1084.1 (B), Internet Explorer 8 (C):

每个测试在三个浏览器上执行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

Similar experiments:

Apparently other people have carried out similar experiments; this one has some useful statistics as well: little link.

显然其他人也进行了类似的实验;这个也有一些有用的统计数据:很少的链接。


The bottom line:

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.

Suppose you're building a chat page, and you want to style all the messages. You know that each message is in a div which has a title and is nested within a div with a class .chatpage. It is correct to use .chatpage div[title] to select the messages, but it's also bad practice efficiency-wise. It's simpler, more maintainable, and more efficient to give all the messages a class and select them using that class.

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


The fancy one-liner conclusion:

Anything within the limits of "yeah, this CSS makes sense" is okay.

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

#2


11  

Most answers here focus on selector performance as if it were the only thing that matters. I'll try to cover some spriting trivia (spoiler alert: they're not always a good idea), css used value performance and rendering of certain properties.

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

Before I get to the answer, let me get an IMO out of the way: personally, I strongly disagree with the stated need for "evidence-based data". It simply makes a performance claim appear credible, while in reality the field of rendering engines is heterogenous enough to make any such statistical conclusion inaccurate to measure and impractical to adopt or monitor.

在我得到答案之前,让我让IMO走开:就个人而言,我强烈反对所谓的“基于证据的数据”的需求。它简单地使性能声明看起来可信,而实际上渲染引擎的领域是异质的,足以使得任何这样的统计结论不准确以便采用或监视来衡量和不切实际。

As original findings quickly become outdated, I'd rather see front-end devs have an understanding of foundation principles and their relative value against maintainability/readability brownie points - after all, premature optimization is the root of all evil ;)

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


Let's start with selector performance:

Shallow, preferably one-level, specific selectors are processed faster. Explicit performance metrics are missing from the original answer but the key point remains: at runtime an HTML document is parsed into a DOM tree containing N elements with an average depth D and than has a total of S CSS rules applied. To lower computational complexity O(N*D*S), you should

浅,优选一级特定选择器处理更快。原始答案中缺少显式性能指标,但关键点仍然是:在运行时,HTML文档被解析为包含N个元素的DOM树,其中平均深度为D,并且应用了总共S个CSS规则。为了降低计算复杂度O(N * D * S),你应该

  1. Have the right-most keys match as few elements as possible - selectors are matched right-to-left^ for individual rule eligibility so if the right-most key does not match a particular element, there is no need to further process the selector and it is discarded.

    让最右边的键匹配尽可能少的元素 - 选择器从右到左匹配^用于单个规则资格,因此如果最右键与特定元素不匹配,则无需进一步处理选择器和它被丢弃了。

    It is commonly accepted that * selector should be avoided, but this point should be taken further. A "normal" CSS reset does, in fact, match most elements - when this SO page is profiled, the reset is responsible for about 1/3 of all selector matching time so you may prefer normalize.css (still, that only adds up to 3.5ms - the point against premature optimisation stands strong)

    人们普遍认为应该避免使用*选择器,但这一点应该进一步考虑。事实上,“正常”CSS重置确实匹配大多数元素 - 当这个SO页面被分析时,重置负责所有选择器匹配时间的大约1/3,所以你可能更喜欢normalize.css(仍然,这只会加起来)到3.5ms - 反对过早优化的观点很强

  2. Avoid descendant selectors as they require up to ~D elements to be iterated over. This mainly impacts mismatch confirmations - for instance a positive .container .content match may only require one step for elements in a parent-child relationship, but the DOM tree will need to be traversed all the way up to html before a negative match can be confirmed.

    避免使用后代选择器,因为它们需要迭代最多~D个元素。这主要影响不匹配确认 - 例如,积极的.container .content匹配可能只需要父子关系中元素的一个步骤,但是在负匹配之前,需要遍历到DOM树一直到html。证实。

  3. Minimize the number of DOM elements as their styles are applied individually (worth noting, this gets offset by browser logic such as reference caching and recycling styles from identical elements - for instance, when styling identical siblings)

    最小化DOM元素的数量,因为它们的样式是单独应用的(值得注意的是,这会被浏览器逻辑(例如参考缓存和相同元素的回收样式)所抵消 - 例如,在设置相同的兄弟模型时)

  4. Remove unused rules since the browser ends up having to evaluate their applicability for every element rendered. Enough said - the fastest rule is the one that isn't there :)

    删除未使用的规则,因为浏览器最终必须评估它们对每个呈现元素的适用性。够了 - 最快的规则就是没有那个:)

These will result in quantifiable (but, depending on the page, not necessarily perceivable) improvements from a rendering engine performance standpoint, however there are always additional factors such as traffic overhead and DOM parsing etc.

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


Next, CSS3 properties performance:

CSS3 brought us (among other things) rounded corners, background gradients and drop-shadow variations - and with them, a truckload of issues. Think about it, by definition a pre-rendered image performs better than a set of CSS3 rules that has to be rendered first. From webkit wiki:

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

Gradients, shadows, and other decorations in CSS should be used only when necessary (e.g. when the shape is dynamic based on the content) - otherwise, static images are always faster.

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

If that's not bad enough, gradients etc. may have to be recalculated on every repaint/reflow event (more details below). Keep this in mind until the majority of users user can browse a css3-heavy page like this without noticeable lag.

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


Next, spriting performance:

Avoid tall and wide sprites, even if their traffic footprint is relatively small. It is commonly forgotten that a rendering engine cannot work with gif/jpg/png and at runtime all graphical assets are operated with as uncompressed bitmaps. At least it's easy to calculate: this sprite's width times height times four bytes per pixel (RGBA) is 238*1073*4≅1MB. Use it on a few elements across different simultaneously open tabs, and it quickly adds up to a significant value.

即使他们的交通占地面积相对较小,也要避免使用高而宽的精灵。通常会忘记渲染引擎无法使用gif / jpg / png,并且在运行时所有图形资源都使用未压缩的位图进行操作。至少它很容易计算:这个精灵的宽度乘以每像素四个字节(RGBA)的高度为238 * 1073 *4≅1MB。在不同的同时打开的选项卡上的几个元素上使用它,它很快就会产生很大的价值。

A rather extreme case of it has been picked up on mozilla webdev, but this is not at all unexpected when questionable practices like diagonal sprites are used.

在mozilla webdev上已经提到了一个相当极端的情况,但是当使用像对角精灵这样的可疑实践时,这并不是意料之外的。

An alternative to consider is individual base64-encoded images embedded directly into CSS.

另一种考虑因素是将各个base64编码的图像直接嵌入到CSS中。


Next, reflows and repaints:

It is a misconception that a reflow can only be triggered with JS DOM manipulation - in fact, any application of layout-affecting style would trigger it affecting the target element, its children and elements following it etc. The only way to prevent unnecessary iterations of it is to try and avoid rendering dependencies. A straightforward example of this would be rendering tables:

这是一种误解,只能通过JS DOM操作来触发重排 - 实际上,任何影响布局的样式的应用都会触发它影响目标元素,它的子元素和它后面的元素等。防止不必要的迭代的唯一方法它是尝试避免渲染依赖项。一个简单的例子是渲染表:

Tables often require multiple passes before the layout is completely established because they are one of the rare cases where elements can affect the display of other elements that came before them on the DOM. Imagine a cell at the end of the table with very wide content that causes the column to be completely resized. This is why tables are not rendered progressively in all browsers.

在完全建立布局之前,表通常需要多次传递,因为它们是极少数情况之一,其中元素可以影响在DOM之前的其他元素的显示。想象一下表格末尾的一个单元格,内容非常宽,可以使列完全调整大小。这就是为什么表不会在所有浏览器中逐步呈现的原因。


I'll make edits if I recall something important that has been missed. Some links to finish with:

如果我记得一些错过的重要内容,我会进行编辑。一些完成的链接:

http://perfectionkills.com/profiling-css-for-fun-and-profit-optimization-notes/

http://perfectionkills.com/profiling-css-for-fun-and-profit-optimization-notes/

http://jacwright.com/476/runtime-performance-with-css3-vs-images/

http://jacwright.com/476/runtime-performance-with-css3-vs-images/

https://developers.google.com/speed/docs/best-practices/payload

https://developers.google.com/speed/docs/best-practices/payload

https://trac.webkit.org/wiki/QtWebKitGraphics

https://trac.webkit.org/wiki/QtWebKitGraphics

https://blog.mozilla.org/webdev/2009/06/22/use-sprites-wisely/

https://blog.mozilla.org/webdev/2009/06/22/use-sprites-wisely/

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

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

#3


4  

While it's true that

虽然这是真的

computers were way slower 10 years ago.

计算机在10年前变慢了。

You also have a much wider variety of device that are capable of accessing your website these days. And while desktops/laptops have come on in leaps and bounds, the devices in the mid and low end smartphone market, in many cases aren't much more powerful than what we had in desktops ten years ago.

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

But having said that CSS Selection speed is probably near the bottom of the list of things you need to worry about in terms of providing a good experience to as broad a device range as possible.

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

Expanding upon this I was unable to find specific information relating to more modern browsers or mobile devices struggling with inefficient CSS selectors but I was able to find the following:

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

  1. http://www.stevesouders.com/blog/2009/03/10/performance-impact-of-css-selectors/

    http://www.stevesouders.com/blog/2009/03/10/performance-impact-of-css-selectors/

    Quite dated (IE8, Chrome 2) now but has a decent attempt of establishing efficiency of various selectors in some browsers and also tries to quantify how the # of CSS rules impacts page rendering time.

    现在相当过时(IE8,Chrome 2),但在某些浏览器中尝试建立各种选择器的效率,并尝试量化CSS规则如何影响页面渲染时间。

  2. http://www.thebrightlines.com/2010/07/28/css-performance-who-cares/

    http://www.thebrightlines.com/2010/07/28/css-performance-who-cares/

    Again quite dated (IE8, Chrome 6) but goes to extremes in inefficient CSS selectors * * * * * * * * * { background: #ff1; } to establish performance degradation.

    再次过时(IE8,Chrome 6),但在低效的CSS选择器中走向极端* * * * * * * * * {background:#ff1;建立性能下降。

#4


4  

For such a large bounty I am willing to risk the Null answer: there are no official CSS selectors that cause any appreciable slow-downs in the rendering, and (in this day of fast computers and rapid browser iteration) any that are found are quickly solved by browser makers. Even in mobile browsers there is no problem, unless the unwary developer is willing to use non-standard jQuery selectors. These are marked as risky by the jQuery developers, and can indeed be problematic.

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

In this case the lack of evidence is evidence of the lack of problems. So, use semantic markup (especially OOCSS), and report any slow-downs that you find when using standard CSS selectors in obscure browsers.

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

People from the future: CSS performance problems in 2012 were already a thing of the past.

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

#5


1  

isn't css a irrelevant way to make it faster, it must be the last thing you look at when you look at performance. Make your css in what ever way that suites you, compile it. and then put it in the head. This might be rough but their are loads of other things to look for when your looking in to browser performance. If you work at a digital bureau you wont get paid to do that extra 1ms in load time.

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

As i commented use pagespeed for chrome its a google tool that analyze the website in 27 parameters css is 1 of them.

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

My post just concern exactly, wouldn't rather have around 99% of web users be able to open the website and see it right, even the people with IE7 and such. Than closing out around 10% by using css3, (If it turns out that you can get an extra 1-10ms on performance).

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

Most people have atleast 1mbit/512kbit or higher, and if you load a heavy site it takes around 3 secounds to load, but you can save 10ms maybe on css??

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

And when it comes to mobile devices you should make sites just for mobiles so when you have a device with screen size less than "Width"px, you have a separate site

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

Please comment below this is my perspective and my personal experience with web development

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

#6


0  

While not directly code-related, using <link> over @import to include your stylesheets provides much faster performance.

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

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

'不要通过stevesouders.com使用@import'

The article contains numerous speed test examples between each type as well as including one type with another (ex: A CSS file called via <link> also contains @import to another css file).

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

#1


48  

The first thing that comes to mind here is: how clever is the rendering engine you're using?

这里首先想到的是:你正在使用的渲染引擎有多聪明?

That, generic as it sounds, matters a lot when questioning the efficiency of CSS rendering/selection. For instance, suppose the first rule in your CSS file is:

在质疑CSS渲染/选择的效率时,这听起来很通用。例如,假设CSS文件中的第一条规则是:

.class1 {
    /*make elements with "class1" look fancy*/
}

So when a very basic engine sees that (and since this is the first rule), it goes and looks at every element in your DOM, and checks for the existence of class1 in each. Better engines probably map classnames to a list of DOM elements, and use something like a hashtable for efficient lookup.

因此,当一个非常基本的引擎看到(并且因为这是第一个规则)时,它会查看DOM中的每个元素,并检查每个元素中是否存在class1。更好的引擎可能会将类名称映射到DOM元素列表,并使用哈希表之类的东西进行高效查找。

.class1.class2 {
    /*make elements with both "class1" and "class2" look extra fancy*/
}

Our example "basic engine" would go and revisit each element in DOM looking for both classes. A cleverer engine will compare n('class1') and n('class2') where n(str) is number of elements in DOM with the class str, and takes whichever is minimum; suppose that's class1, then passes on all elements with class1 looking for elements that have class2 as well.

我们的示例“基本引擎”将重新访问DOM中的每个元素,以查找这两个类。一个聪明的引擎将比较n('class1')和n('class2'),其中n(str)是DOM中的元素数与str类,并取最小值;假设是class1,然后传递class1的所有元素,同时查找具有class2的元素。

In any case, modern engines are clever (way more clever than the discussed example above), and shiny new processors can do millions (tens of millions) of operations a second. It's quite unlikely that you have millions of elements in your DOM, so the worst-case performance for any selection (O(n)) won't be too bad anyhow.

在任何情况下,现代引擎都很聪明(比上面讨论的例子更聪明),闪亮的新处理器每秒可以进行数百万(数千万)次操作。你的DOM中有数百万个元素是不太可能的,因此无论如何,任何选择(O(n))的最坏情况都不会太糟糕。


Update:

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 elements (tested on my personal main page).
Google: ~340 elements (tested on the main page, no search results).
Google: ~950 elements (tested on a search result page).
Yahoo!: ~1400 elements (tested on the main page).
*: ~680 elements (tested on a question page).
AOL: ~1060 elements (tested on the main page).
Wikipedia: ~6000 elements, 2420 of which aren't spans or anchors (Tested on the Wikipedia article about Glee).
Twitter: ~270 elements (tested on the main page).

Facebook:约1900个元素(在我的个人主页上测试)。谷歌:~340个元素(在主页上测试,没有搜索结果)。谷歌:~950个元素(在搜索结果页面上测试)。雅虎!:~1400个元素(在主页上测试)。 *:约680个元素(在问题页面上测试)。 AOL:~1060个元素(在主页上测试)。*:~6000个元素,其中2420个不是跨度或锚点(在*关于Glee的文章中测试过)。 Twitter:~270个元素(在主页上测试)。

Summing those up, we get an average of ~1500 elements. Now it's time to do some testing. For each test, I generated 1500 divs (nested within some other divs for some tests), each with appropriate attributes depending on the test.

总结一下,我们得到平均约1500个元素。现在是时候做一些测试了。对于每个测试,我生成了1500个div(嵌套在一些其他div中用于某些测试),每个div都具有适当的属性,具体取决于测试。


The tests

The styles and elements are all generated using PHP. I've uploaded the PHPs I used, and created an index, so that others can test locally: little link.

样式和元素都是使用PHP生成的。我已经上传了我使用的PHP,并创建了一个索引,以便其他人可以在本地测试:小链接。


Results:

Each test is performed 5 times on three browsers (the average time is reported): Firefox 15.0 (A), Chrome 19.0.1084.1 (B), Internet Explorer 8 (C):

每个测试在三个浏览器上执行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

Similar experiments:

Apparently other people have carried out similar experiments; this one has some useful statistics as well: little link.

显然其他人也进行了类似的实验;这个也有一些有用的统计数据:很少的链接。


The bottom line:

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.

Suppose you're building a chat page, and you want to style all the messages. You know that each message is in a div which has a title and is nested within a div with a class .chatpage. It is correct to use .chatpage div[title] to select the messages, but it's also bad practice efficiency-wise. It's simpler, more maintainable, and more efficient to give all the messages a class and select them using that class.

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


The fancy one-liner conclusion:

Anything within the limits of "yeah, this CSS makes sense" is okay.

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

#2


11  

Most answers here focus on selector performance as if it were the only thing that matters. I'll try to cover some spriting trivia (spoiler alert: they're not always a good idea), css used value performance and rendering of certain properties.

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

Before I get to the answer, let me get an IMO out of the way: personally, I strongly disagree with the stated need for "evidence-based data". It simply makes a performance claim appear credible, while in reality the field of rendering engines is heterogenous enough to make any such statistical conclusion inaccurate to measure and impractical to adopt or monitor.

在我得到答案之前,让我让IMO走开:就个人而言,我强烈反对所谓的“基于证据的数据”的需求。它简单地使性能声明看起来可信,而实际上渲染引擎的领域是异质的,足以使得任何这样的统计结论不准确以便采用或监视来衡量和不切实际。

As original findings quickly become outdated, I'd rather see front-end devs have an understanding of foundation principles and their relative value against maintainability/readability brownie points - after all, premature optimization is the root of all evil ;)

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


Let's start with selector performance:

Shallow, preferably one-level, specific selectors are processed faster. Explicit performance metrics are missing from the original answer but the key point remains: at runtime an HTML document is parsed into a DOM tree containing N elements with an average depth D and than has a total of S CSS rules applied. To lower computational complexity O(N*D*S), you should

浅,优选一级特定选择器处理更快。原始答案中缺少显式性能指标,但关键点仍然是:在运行时,HTML文档被解析为包含N个元素的DOM树,其中平均深度为D,并且应用了总共S个CSS规则。为了降低计算复杂度O(N * D * S),你应该

  1. Have the right-most keys match as few elements as possible - selectors are matched right-to-left^ for individual rule eligibility so if the right-most key does not match a particular element, there is no need to further process the selector and it is discarded.

    让最右边的键匹配尽可能少的元素 - 选择器从右到左匹配^用于单个规则资格,因此如果最右键与特定元素不匹配,则无需进一步处理选择器和它被丢弃了。

    It is commonly accepted that * selector should be avoided, but this point should be taken further. A "normal" CSS reset does, in fact, match most elements - when this SO page is profiled, the reset is responsible for about 1/3 of all selector matching time so you may prefer normalize.css (still, that only adds up to 3.5ms - the point against premature optimisation stands strong)

    人们普遍认为应该避免使用*选择器,但这一点应该进一步考虑。事实上,“正常”CSS重置确实匹配大多数元素 - 当这个SO页面被分析时,重置负责所有选择器匹配时间的大约1/3,所以你可能更喜欢normalize.css(仍然,这只会加起来)到3.5ms - 反对过早优化的观点很强

  2. Avoid descendant selectors as they require up to ~D elements to be iterated over. This mainly impacts mismatch confirmations - for instance a positive .container .content match may only require one step for elements in a parent-child relationship, but the DOM tree will need to be traversed all the way up to html before a negative match can be confirmed.

    避免使用后代选择器,因为它们需要迭代最多~D个元素。这主要影响不匹配确认 - 例如,积极的.container .content匹配可能只需要父子关系中元素的一个步骤,但是在负匹配之前,需要遍历到DOM树一直到html。证实。

  3. Minimize the number of DOM elements as their styles are applied individually (worth noting, this gets offset by browser logic such as reference caching and recycling styles from identical elements - for instance, when styling identical siblings)

    最小化DOM元素的数量,因为它们的样式是单独应用的(值得注意的是,这会被浏览器逻辑(例如参考缓存和相同元素的回收样式)所抵消 - 例如,在设置相同的兄弟模型时)

  4. Remove unused rules since the browser ends up having to evaluate their applicability for every element rendered. Enough said - the fastest rule is the one that isn't there :)

    删除未使用的规则,因为浏览器最终必须评估它们对每个呈现元素的适用性。够了 - 最快的规则就是没有那个:)

These will result in quantifiable (but, depending on the page, not necessarily perceivable) improvements from a rendering engine performance standpoint, however there are always additional factors such as traffic overhead and DOM parsing etc.

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


Next, CSS3 properties performance:

CSS3 brought us (among other things) rounded corners, background gradients and drop-shadow variations - and with them, a truckload of issues. Think about it, by definition a pre-rendered image performs better than a set of CSS3 rules that has to be rendered first. From webkit wiki:

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

Gradients, shadows, and other decorations in CSS should be used only when necessary (e.g. when the shape is dynamic based on the content) - otherwise, static images are always faster.

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

If that's not bad enough, gradients etc. may have to be recalculated on every repaint/reflow event (more details below). Keep this in mind until the majority of users user can browse a css3-heavy page like this without noticeable lag.

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


Next, spriting performance:

Avoid tall and wide sprites, even if their traffic footprint is relatively small. It is commonly forgotten that a rendering engine cannot work with gif/jpg/png and at runtime all graphical assets are operated with as uncompressed bitmaps. At least it's easy to calculate: this sprite's width times height times four bytes per pixel (RGBA) is 238*1073*4≅1MB. Use it on a few elements across different simultaneously open tabs, and it quickly adds up to a significant value.

即使他们的交通占地面积相对较小,也要避免使用高而宽的精灵。通常会忘记渲染引擎无法使用gif / jpg / png,并且在运行时所有图形资源都使用未压缩的位图进行操作。至少它很容易计算:这个精灵的宽度乘以每像素四个字节(RGBA)的高度为238 * 1073 *4≅1MB。在不同的同时打开的选项卡上的几个元素上使用它,它很快就会产生很大的价值。

A rather extreme case of it has been picked up on mozilla webdev, but this is not at all unexpected when questionable practices like diagonal sprites are used.

在mozilla webdev上已经提到了一个相当极端的情况,但是当使用像对角精灵这样的可疑实践时,这并不是意料之外的。

An alternative to consider is individual base64-encoded images embedded directly into CSS.

另一种考虑因素是将各个base64编码的图像直接嵌入到CSS中。


Next, reflows and repaints:

It is a misconception that a reflow can only be triggered with JS DOM manipulation - in fact, any application of layout-affecting style would trigger it affecting the target element, its children and elements following it etc. The only way to prevent unnecessary iterations of it is to try and avoid rendering dependencies. A straightforward example of this would be rendering tables:

这是一种误解,只能通过JS DOM操作来触发重排 - 实际上,任何影响布局的样式的应用都会触发它影响目标元素,它的子元素和它后面的元素等。防止不必要的迭代的唯一方法它是尝试避免渲染依赖项。一个简单的例子是渲染表:

Tables often require multiple passes before the layout is completely established because they are one of the rare cases where elements can affect the display of other elements that came before them on the DOM. Imagine a cell at the end of the table with very wide content that causes the column to be completely resized. This is why tables are not rendered progressively in all browsers.

在完全建立布局之前,表通常需要多次传递,因为它们是极少数情况之一,其中元素可以影响在DOM之前的其他元素的显示。想象一下表格末尾的一个单元格,内容非常宽,可以使列完全调整大小。这就是为什么表不会在所有浏览器中逐步呈现的原因。


I'll make edits if I recall something important that has been missed. Some links to finish with:

如果我记得一些错过的重要内容,我会进行编辑。一些完成的链接:

http://perfectionkills.com/profiling-css-for-fun-and-profit-optimization-notes/

http://perfectionkills.com/profiling-css-for-fun-and-profit-optimization-notes/

http://jacwright.com/476/runtime-performance-with-css3-vs-images/

http://jacwright.com/476/runtime-performance-with-css3-vs-images/

https://developers.google.com/speed/docs/best-practices/payload

https://developers.google.com/speed/docs/best-practices/payload

https://trac.webkit.org/wiki/QtWebKitGraphics

https://trac.webkit.org/wiki/QtWebKitGraphics

https://blog.mozilla.org/webdev/2009/06/22/use-sprites-wisely/

https://blog.mozilla.org/webdev/2009/06/22/use-sprites-wisely/

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

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

#3


4  

While it's true that

虽然这是真的

computers were way slower 10 years ago.

计算机在10年前变慢了。

You also have a much wider variety of device that are capable of accessing your website these days. And while desktops/laptops have come on in leaps and bounds, the devices in the mid and low end smartphone market, in many cases aren't much more powerful than what we had in desktops ten years ago.

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

But having said that CSS Selection speed is probably near the bottom of the list of things you need to worry about in terms of providing a good experience to as broad a device range as possible.

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

Expanding upon this I was unable to find specific information relating to more modern browsers or mobile devices struggling with inefficient CSS selectors but I was able to find the following:

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

  1. http://www.stevesouders.com/blog/2009/03/10/performance-impact-of-css-selectors/

    http://www.stevesouders.com/blog/2009/03/10/performance-impact-of-css-selectors/

    Quite dated (IE8, Chrome 2) now but has a decent attempt of establishing efficiency of various selectors in some browsers and also tries to quantify how the # of CSS rules impacts page rendering time.

    现在相当过时(IE8,Chrome 2),但在某些浏览器中尝试建立各种选择器的效率,并尝试量化CSS规则如何影响页面渲染时间。

  2. http://www.thebrightlines.com/2010/07/28/css-performance-who-cares/

    http://www.thebrightlines.com/2010/07/28/css-performance-who-cares/

    Again quite dated (IE8, Chrome 6) but goes to extremes in inefficient CSS selectors * * * * * * * * * { background: #ff1; } to establish performance degradation.

    再次过时(IE8,Chrome 6),但在低效的CSS选择器中走向极端* * * * * * * * * {background:#ff1;建立性能下降。

#4


4  

For such a large bounty I am willing to risk the Null answer: there are no official CSS selectors that cause any appreciable slow-downs in the rendering, and (in this day of fast computers and rapid browser iteration) any that are found are quickly solved by browser makers. Even in mobile browsers there is no problem, unless the unwary developer is willing to use non-standard jQuery selectors. These are marked as risky by the jQuery developers, and can indeed be problematic.

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

In this case the lack of evidence is evidence of the lack of problems. So, use semantic markup (especially OOCSS), and report any slow-downs that you find when using standard CSS selectors in obscure browsers.

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

People from the future: CSS performance problems in 2012 were already a thing of the past.

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

#5


1  

isn't css a irrelevant way to make it faster, it must be the last thing you look at when you look at performance. Make your css in what ever way that suites you, compile it. and then put it in the head. This might be rough but their are loads of other things to look for when your looking in to browser performance. If you work at a digital bureau you wont get paid to do that extra 1ms in load time.

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

As i commented use pagespeed for chrome its a google tool that analyze the website in 27 parameters css is 1 of them.

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

My post just concern exactly, wouldn't rather have around 99% of web users be able to open the website and see it right, even the people with IE7 and such. Than closing out around 10% by using css3, (If it turns out that you can get an extra 1-10ms on performance).

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

Most people have atleast 1mbit/512kbit or higher, and if you load a heavy site it takes around 3 secounds to load, but you can save 10ms maybe on css??

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

And when it comes to mobile devices you should make sites just for mobiles so when you have a device with screen size less than "Width"px, you have a separate site

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

Please comment below this is my perspective and my personal experience with web development

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

#6


0  

While not directly code-related, using <link> over @import to include your stylesheets provides much faster performance.

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

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

'不要通过stevesouders.com使用@import'

The article contains numerous speed test examples between each type as well as including one type with another (ex: A CSS file called via <link> also contains @import to another css file).

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