将 &-nesting与 :has伪类结合使用会导致性能瓶颈

前端开发 2026-07-12

想象下面这个CSS规则,我在样式表中使用过:

.toplevel .small-container svg:has(> g[opacity="0.3"]) {
  > g[opacity="0.3"],
  + .sibling-el {
    opacity: .6 !important;
  }
}

当使用上述规则时,动态内容的性能会完全崩溃。虽然来自 :has 的性能损耗总是难以避免,但这甚至会在DOM中没有带有 .small-container-class的元素时发生。似乎仍在对 :has() 进行评估,尽管评估本应在未找到 .small-container 时结束。

把它改写为

.toplevel {
  .small-container svg:has(> g[opacity="0.3"]) + .sibling-el,
  .small-container svg > g[opacity="0.3"] {
    opacity: .6 !important;
  }
}

就能完全解决性能问题。

我很好奇这是为什么……你认为这是浏览器的问题吗?浏览器没有正确地组合选择器?还是我对 &-nesting的工作方式还有误解?

解决方案

首先,这些选择器产生了以下结果:

/* 1st */
.toplevel .small-container svg:has(> g[opacity="0.3"]) > g[opacity="0.3"],
.toplevel .small-container svg:has(> g[opacity="0.3"]) + .sibling-el { }

/* 2nd */
.toplevel .small-container svg:has(> g[opacity="0.3"]) + .sibling-el,
.toplevel .small-container svg > g[opacity="0.3"] { }

在这里,“结果”是指浏览器实际计算出的内容。


接下来我们看到这一段:

...evaluation should have ended, when no .small-container was found.

如果从左到右读取,这当然成立。问题在于,CSS的评估是从右到左进行的

也许你把 .small-container 的名字改了以防止匹配,但引擎先查找 g[...].sibling-el,然后是 svg:has(...),再是那个 :has 的内容,最后在未找到 .small-container 时中止。


这是一个bug吗?

我认为不是,尤其是因为这些实际上是两个不同的、非等价的选择器。

关于性能,这里应该会有改进,因为 has 仍然是一个新特性。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章