【问题标题】:Is declaring "content" property on :before and :after for every element a massive performance issue?在 :before 和 :after 上为每个元素声明“内容”属性是一个巨大的性能问题吗?
【发布时间】:2013-10-15 11:05:03
【问题描述】:

您可能知道,如果您要使用 :before 和/或 :after 伪元素而不在其中设置文本,您仍然必须在它们上声明 content: ''; 以使其可见。

我刚刚在我的基本样式表中添加了以下内容:

*:before, *:after {
    content: '';
}

...所以我不必再声明了。

除了* 选择器是反性能的,我知道这一点(假设上面是一个示例,我可以找到更好的方法来声明它,例如而是列出标签),这真的会减慢速度吗?在我当前的项目中,我没有注意到任何视觉上的东西,但我想确保在我将它明确粘贴到我将用于每个项目的基本样式表之前,它可以安全使用...

有人对此进行过深入测试吗?对此你有什么想说的?

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

【问题讨论】:

    标签: css performance pseudo-element css-content


    【解决方案1】:

    所以我根据@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 填充 div.container。就我而言,我去了 html-ipsum.com(没有广告的意图),复制每个样本,将它们全部缩小,然后复制了很多次。我的最终 HTML 文件是 1.70 MBdiv.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)在空的&lt;style&gt;标签中添加我们要测试的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 毫秒)

    现在,剩下的问题是:考虑到使用的测试页面相对较大,我们可以在这里看到的额外加载时间是否有意义?我想这取决于网站/项目的规模,但如果他们愿意,我会让更多的网络性能知识渊博的人在这里发表意见。

    如果您运行自己的测试,也请随时在此处发布您的结论,因为我对阅读它们非常感兴趣 - 我想我不会是唯一的。

    【讨论】:

    • 我想到的解释是,这将在每个标签之前和之后插入一个伪元素,包括那些原本不需要它们的伪元素(在这个测试中,它是每个标签) .它基本上是页面上元素数量的三倍。
    • @user1618143 这是一个很好的观点,但我的想法是它可能依赖于浏览器,因为 *:before*:after 规则在技术上是 just 样式规则,不是伪元素创建规则(理论上)。也许某些浏览器总是在页面上的每个真实元素中创建两个隐藏的伪元素,因此 CSS 规则不会导致您指出的问题。另一方面,其他浏览器可能只会在样式规则以它们为目标时被动地创建伪元素,在这种情况下,确实会在所有具有这些规则的真实元素上创建过多的伪元素。
    • 我还想知道单个标签定位(而不是使用*)是否不允许浏览器做出某些优化假设,因为它现在必须根据列表检查每个标签样式,而不是知道 * 规则无论如何都适用于任何标签。另外,我认为如果您在没有扩展/附加组件的情况下这样做,对 FF 会更公平。不知道扩展程序对页面做了什么样的幕后操作,因此您的 FF 统计数据可能会被它们混淆。
    • @ajp15243:从技术上讲,它们可能只是样式规则,但“不要费心包含没有样式的伪元素”让我觉得浏览器优化很简单。
    • @user1618143 我同意,但我见过更蠢的东西:)。
    【解决方案2】:

    我的回答是:我不知道,但可以测试一下。

    阅读Navigation Timing 并查看此example page

    最简单的用法示例:

    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:等待您的结果信息。知道这些事情就好了。
    猜你喜欢
    • 2012-01-05
    • 2013-06-08
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 2012-12-01
    • 1970-01-01
    • 2018-09-03
    • 2015-05-06
    相关资源
    最近更新 更多