CSS 性能,#id vs .class vs [^regex$] vs 选择器

标签 css performance performance-testing

我已经看到执行以下操作会影响性能:

a[rel^=ext] {

这是有道理的。但我还在我使用的模板中找到了一些代码,这些代码为网站上的每个部分执行此操作:

@print {
 #section-name {
  color: #000;
  background: #fff;
 }
} 

我想我可以只使用 [^] 来选择它们并制定一个规则并节省代码行。然后我发现这会影响性能。

于是查看了一下,发现有一个id为外层的div。所以我想我可以做 #idName section

但是它使用了一个元素,所以我认为这可能会再次影响性能。

有没有人有任何信息可以让我找到更多关于性能的信息以及哪种方式最快。例如是更大文件的性能更差还是许多选择器的计算更差?

作为进一步的一部分,我发现这种事情很有趣,有没有人有一个好的,可靠的方法来测试这些东西?使用在线服务每次都会给出不同的结果,因此需要数千次才能得出好的数字。有谁知道执行这些操作的好方法吗?

最佳答案

根据 Eoin 的要求,我正在为 future 的访问者提供答案(因为我认为这很有用)。

来自此链接:https://www.sitepoint.com/optimizing-css-id-selectors-and-other-myths/

以下代码段在 50,000 个节点上运行。控制台输出将为您提供有关特定选择器性能的答案。

const createFragment = html =>
  document.createRange().createContextualFragment(html);

const btn = document.querySelector(".btn");
const container = document.querySelector(".box-container");
const count = 50000;
const selectors = [
  "div",
  ".box",
  ".box > .title",
  ".box .title",
  ".box ~ .box",
  ".box + .box",
  ".box:last-of-type",
  ".box:nth-of-type(2n - 1)",
  ".box:not(:last-of-type)",
  ".box:not(:empty):last-of-type .title",
  ".box:nth-last-child(n+6) ~ div",

];
let domString = "";

const box = count => `
<div class="box">
  <div class="title">${count}</div>
</div>`;

btn.addEventListener("click", () => {
  console.log('-----\n');
  selectors.forEach(selector => {
    console.time(selector);
    document.querySelectorAll(selector);
    console.timeEnd(selector);
  });
});

for (let i = 0; i < count; i++) {
  domString += box(i + 1);
}

container.append(createFragment(domString));
body {
  font-family: sans-serif;
}

* {
  box-sizing: border-box;
}

.btn {
  background: #000;
  display: block;
  appearance: none;
  margin: 20px auto;
  color: #FFF;
  font-size: 24px;
  border: none;
  border-radius: 5px;
  padding: 10px 20px;
}

.box-container {
  background: #E0E0E0;
  display: flex;
  flex-wrap: wrap;
}

.box {
  background: #FFF;
  padding: 10px;
  width: 25%
}
<button class="btn">Measure</button>
<div class="box-container"></div>

同样来自 sitepoint 链接,这里有一些更多的数据和信息来支持它:

The test was bumped up a bit, to 50000 elements, and you can test it out yourself. I did an average of 10 runs on my 2014 MacBook Pro, and what I got was the following:

  • Selector : Query Time (ms)
  • div : 4.8740
  • .box : 3.625
  • .box > .title : 4.4587
  • .box .title : 4.5161
  • .box ~ .box : 4.7082
  • .box + .box : 4.6611
  • .box:last-of-type : 3.944
  • .box:nth-of-type(2n - 1) : 16.8491
  • .box:not(:last-of-type) : 5.8947
  • .box:not(:empty):last-of-type .title : 8.0202
  • .box:nth-last-child(n+6) ~ div : 20.8710

The results will of course vary depending on whether you use querySelector or querySelectorAll, and the number of matching nodes on the page, but querySelectorAll comes closer to the real use case of CSS, which is targeting all matching elements.

Even in such an extreme case, with 50000 elements to match, and using some really insane selectors like the last one, we find that the slowest one is ~20ms, while the fastest is the simple class at ~3.5ms. Not really that much of a difference. In a realistic, more “tame” DOM, with around 1000–5000 nodes, you can expect those results to drop by a factor of 10, bringing them to sub-millisecond parsing speeds.

这一切的收获:

What we can see from this test is that it’s not really worth it to worry over CSS selector performance. Just don’t overdo it with pseudo selectors and really long selectors.

这里的另一个测试:https://benfrain.com/css-performance-revisited-selectors-bloat-expensive-styles/涵盖数据属性和正则表达式选择器。它发现:

  1. Data attribute
  2. Data attribute (qualified)
  3. Data attribute (unqualified but with value)
  4. Data attribute (qualified with value)
  5. Multiple data attributes (qualified with values)
  6. Solo pseudo selector (e.g. :after)
  7. Combined classes (e.g. class1.class2)
  8. Multiple classes
  9. Multiple classes with child selector
  10. Partial attribute matching (e.g. [class^=“wrap”])
  11. nth-child selector
  12. nth-child selector followed by another nth-child selector
  13. Insanity selection (all selections qualified, every class used e.g. div.wrapper > div.tagDiv > div.tagDiv.layer2 > ul.tagUL >
  14. li.tagLi > b.tagB > a.TagA.link)
  15. Slight insanity selection (e.g. .tagLi .tagB a.TagA.link)
  16. Universal selector
  17. Element single
  18. Element double
  19. Element treble
  20. Element treble with pseudo
  21. Single class

这是结果。您应该注意到它们来自 2014 年的浏览器。所有时间以毫秒为单位:

Test    Chrome 34   Firefox 29  Opera 19    IE9     Android 4
1       56.8        125.4       63.6        152.6   1455.2
2       55.4        128.4       61.4        141     1404.6
3       55          125.6       61.8        152.4   1363.4
4       54.8        129         63.2        147.4   1421.2
5       55.4        124.4       63.2        147.4   1411.2
6       60.6        138         58.4        162     1500.4
7       51.2        126.6       56.8        147.8   1453.8
8       48.8        127.4       56.2        150.2   1398.8
9       48.8        127.4       55.8        154.6   1348.4
10      52.2        129.4       58          172     1420.2
11      49          127.4       56.6        148.4   1352
12      50.6        127.2       58.4        146.2   1377.6
13      64.6        129.2       72.4        152.8   1461.2
14      50.2        129.8       54.8        154.6   1381.2
15      50          126.2       56.8        154.8   1351.6
16      49.2        127.6       56          149.2   1379.2
17      50.4        132.4       55          157.6   1386
18      49.2        128.8       58.6        154.2   1380.6
19      48.6        132.4       54.8        148.4   1349.6
20      50.4        128         55          149.8   1393.8
Biggest Diff.   
        16          13.6        17.6        31      152
Slowest         
        13          6           13          10      6

关于CSS 性能,#id vs .class vs [^regex$] vs 选择器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58274139/

相关文章:

html - 如何用CSS实现自定义图标字体

c++ - OpenCV 和 MATLAB 速度比较

javascript - 如何在 Javascript 中捕获用户操作所消耗的时间?

c# - 将 T 解析为 int、float、decimal 或 double 来比较计算性能

javascript - jquery ui selectmenu 小部件的最低 css 和 js 要求是什么?

javascript - 使用字符串值javascript设置样式

performance - childNodeWithName在SpriteKit中的表现如何?

performance - IIS 6.0 服务器太忙 HTTP 503 Connection_Dropped DefaultAppPool

testing - 如何计算负载测试中使用的并发用户数?

html - 列表显示内联文本 text-overflow