CSS选择器更改后显着性能下降

时间:2016-01-20 18:30:09

标签: css performance css-selectors

我在一个相当复杂的Web应用程序中对一些SASS选择器进行了一些小改动,并且看到了显着的性能下降。使用Chrome的时间轴功能对页面进行概要分析时,"重新计算样式" (在我假设的DOM操作之后回流页面)从大约1ms变为大约100ms,并且受影响的元素计数这些样式重新计算从大约10变为大约1500.

是什么让这个选择器变得如此邪恶?在将来,我应该警惕什么才能不再犯同样的错误?

原创CSS(快速):

.button-group .button:not(:last-of-type) {
  margin-right: -1px;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
.button-group .button:not(:first-of-type) {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}

修改CSS(非常慢):

.button-group > :not(:first-of-type) .button, .button-group > :not(:first-of-type).button {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}
.button-group > :not(:last-of-type) .button, .button-group > :not(:last-of-type).button {
  margin-right: -1px;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}

1 个答案:

答案 0 :(得分:0)

为了打破这一点,我将忽略.button-group,因为两者都是一样的,不会影响任何事情。

在第一个示例中,您选择每个button类。浏览器针对搜索类进行了优化,因此通常非常快。然后使用not(:last-of-type)修饰符,这个修饰符较慢,但无关紧要,因为池已经仅限于button类。

在第二个示例中,首先搜索:not(:first-of-type),这会对.button-group的每个孩子执行昂贵的操作。虽然使用直接子操作符(>)将有助于限制该池,但它可能仍然是比第一个示例更多的元素。我不太确定你要用.button, &.button做什么,但无论哪种方式,操作都不是很昂贵,因为你只是按类选择而且你已经把游戏池限制了很多。

因此,一般而言,您希望从成本最低的操作转到成本最高的操作,以便在尽可能少的元素上进行密集计算。

旁注,我想你在第二个例子中.button之后错过了一个逗号。

编辑:只想指出两段代码编译的区别。

首先:

.button-group .button:not(:last-of-type)

第二

.button-group > :not(:first-of-type) .button, 
.button-group > :not(:first-of-type).button {

正如你所看到的,第二种情况还有很多。仅此一点可能是它变慢的原因,尽管我现在正在检查以确保not的排序有影响。