在每个元素的:before和:after上声明"content"属性是否会对性能造成巨大影响?

8
您可能已经知道,如果您想使用:before和/或:after伪元素而不在其中设置文本,则仍然必须在它们上声明content: '';以使它们可见。
我刚刚将以下内容添加到我的基本样式表中:
*:before, *:after {
    content: '';
}

...所以我不需要再进一步声明它了。

除了我已经意识到的*选择器的性能问题(假设上面的代码只是一个例子,我可以找到更好的方法来声明,比如列出标签),这样做会让网页变慢吗?在我的当前项目中我没有注意到任何视觉上的问题,但是在我把它确定地放入我将用于每个项目的基础样式表之前,我想确保这是安全使用的...

有人对此进行了深入测试吗?你对此有什么看法?

(顺便说一下,我知道正确的CSS3语法使用双分号(::before::after),因为它们是伪元素而不是伪类。)

2个回答

7

我根据@SWilk的建议进行了一些测试。 这是我如何做到的:

1)在<head>中设置一个空的<style>标签,并在<body>底部的<script>标签中提供简单示例:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>Performance test</title>

    <style>
/**/
    </style>
</head>

<body onload="onLoad()">
    <div class="container"></div>

    <script>
function onLoad() {
    var now = new Date().getTime();
    var page_load_time = now - performance.timing.navigationStart;
    console.log("User-perceived page loading time: " + page_load_time);
}
    </script>
</body>

</html>

2)用大量HTML填充

。在我的情况下,我去了html-ipsum.com(没有广告意图),复制了每个样本,将它们全部压缩在一起,并重复了多次。 我的最终HTML文件大小为1.70MBdiv.container33264个后代(直接或间接;我通过调用console.log(document.querySelectorAll('.container *').length);发现的)。

3)我在最新版本的Firefox和Chrome中运行了这个页面10次,每次都清空缓存。

以下是不包含可怕的CSS规则集的结果(以毫秒为单位):

Firefox :
1785
1503
1435
1551
1526
1429
1754
1526
2009
1486
Average : 1600

Chrome :
1102
1046
1073
1028
1038
1026
1011
1016
1035
985
Average : 1036

(如果你想知道这两者之间为什么有这么大的差异,那是因为我在Firefox上安装了更多的扩展。我让它们保留是因为我认为这样可以进一步多样化测试环境。)
4) 在空的<style>标签中添加我们要测试的CSS。
html:before, html:after,
body:before, body:after,
div:before, div:after,
p:before, p:after,
ul:before, ul:after,
li:before, li:after,
h1:before, div:after,
strong:before, strong:after,
em:before, em:after,
code:before, code:after,
h2:before, div:after,
ol:before, ol:after,
blockquote:before, blockquote:after,
h3:before, div:after,
pre:before, pre:after,
form:before, form:after,
label:before, label:after,
input:before, input:after,
table:before, table:after,
thead:before, thead:after,
tbody:before, tbody:after,
tr:before, tr:after,
th:before, th:after,
td:before, td:after,
dl:before, dl:after,
dt:before, dt:after,
dd:before, dd:after,
nav:before, nav:after {
    content: '';
}

...然后重新开始。在这里,我会列出页面中使用的每个标签,而不是*(因为它本身具有反性能,我们只想监视伪元素触发)。

因此,以下是所有伪元素触发的结果(仍以毫秒为单位):

Firefox :
1608
1885
1882
2035
2046
1987
2049
2376
1959
2160
Average : 1999

Chrome :
1517
1594
1582
1556
1548
1545
1553
1525
1542
1537
Average : 1550

根据这些数据,我们可以得出结论:在每个伪元素上声明“content: ''”时,页面加载确实会变慢(大约400-500毫秒)。
现在,剩下的问题是:考虑到使用的相对较大的测试页面,我们在这里看到的额外加载时间是否具有意义?我想这取决于网站/项目的规模,但如果他们愿意,我会让更了解网络性能的人在这里发表他们的意见。
如果您进行自己的测试,请随时在此处发布您的结论,因为我非常有兴趣阅读它们 - 而且我认为我不会是唯一一个。

1
脑海中浮现的解释是,这将在每个标签之前和之后插入一个伪元素,包括那些本来不需要它们的标签(在这个测试中,是每个标签)。这基本上是将页面上的元素数量增加了三倍。 - user1618143
1
我也在想,个别标签定位(而不是使用 *)是否能够让浏览器做出某些优化的假设,因为现在它必须检查每个标签与样式列表相比较,而不是知道 * 规则将适用于任何标签。此外,如果您没有使用扩展/附加组件,那么对于 FF 来说会更公平。无法确定扩展程序对页面执行了什么样的幕后操作,因此它们可能会混淆您的 FF 统计数据。 - ajp15243
@ajp15243:它们在技术上可能只是样式规则,但“不要包含没有样式的伪元素”对于浏览器优化来说似乎是一个显而易见的选择。 - user1618143
猜想这样做可以节省编写CSS的时间,然后使用一些Grunt的魔法来删除*(或逐个元素)规则,并向所有尚未声明此属性的:before:after规则添加content: '';。听起来可行吗?我还没有使用Grunt等工具。 - neemzy
记录一下,设置 *:before, *:after { content: ''; } 会导致当前 Chrome 出现意外行为,所以绝对不可行。 - neemzy
显示剩余3条评论

2
我的答案是:我不知道,但可以进行测试。
阅读关于导航计时的内容并查看这个示例页面
最简单的使用示例:
function onLoad() { 
  var now = new Date().getTime();
  var page_load_time = now - performance.timing.navigationStart;
  console.log("User-perceived page loading time: " + page_load_time);
}

所以,生成一些带有随机标签的几 MB HTML,并进行测试。

谢谢!我会运行一些测试并发布我的结果。 - neemzy
@neemzy:等待您的结果信息。了解这些事情会很好。 - Akshay Khandelwal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接