【问题标题】:Is !important bad for performance?!important 对性能有害吗?
【发布时间】:2012-11-24 11:38:50
【问题描述】:

我讨厌它们,它违背了 CSS 的级联特性,如果你不小心使用它们,你最终会陷入添加更多 !important 的循环。

但我想知道它们对性能有害吗?

编辑
从(快速)回复中,我可以得出结论,它不会对性能产生(显着)影响。 但很高兴知道,即使这只是作为劝阻他人的额外论据;)。

编辑 2
BoltClock 指出,如果有 2 个 !important 声明,规范会选择最具体的一个。

【问题讨论】:

  • 出于好奇,您如何评估 CSS 样式表的性能?更好的 CSS 渲染更快还是什么?
  • @Yoshi 它仍然需要寻找其他!important 规则。
  • @janw:我刚刚澄清说它确实选择了最具体的一个......我已经删除了误导性评论。
  • 随机想:如果标题写成:“重要吗?重要吗?”
  • 我总是把 !important 读作“不重要”

标签: css performance


【解决方案1】:

它不应该对性能产生任何明显的影响。在 /source/layout/style/nsCSSDataBlock.cpp#572 看到 Firefox 的 CSS 解析器,我认为这是相关的例程,处理 CSS 规则的覆盖

这似乎只是对“重要”的简单检查。

  if (aIsImportant) {
    if (!HasImportantBit(aPropID))
      changed = PR_TRUE;
    SetImportantBit(aPropID);
  } else {
    // ...
  }

另外,source/layout/style/nsCSSDataBlock.h#219

    /**
     * Transfer the state for |aPropID| (which may be a shorthand)
     * from |aFromBlock| to this block.  The property being transferred
     * is !important if |aIsImportant| is true, and should replace an
     * existing !important property regardless of its own importance
     * if |aOverrideImportant| is true.
     * 
     * ...
     */

  1. Firefox 使用手动编写的自顶向下解析器。在这两种情况下 CSS 文件被解析成一个 StyleSheet 对象,每个对象都包含 CSS 规则。

  2. Firefox 然后创建包含结束值的样式上下文树 (按正确顺序应用所有规则后)

From: http://taligarsiel.com/Projects/howbrowserswork1.htm#CSS_parsing

现在,您可以很容易地看到,在上述对象模型的情况下,解析器可以轻松标记受!important 影响的规则,而无需太多后续成本。性能下降不是反对!important的好论据。

但是,可维护性确实会受到影响(正如其他答案所述),这可能是您反对它们的唯一论据。

【讨论】:

  • 我喜欢你是唯一一个麻烦检查而不是假设的人。干得好,先生!
  • 这个对象模型不是 DOM,顺便说一下……它是 CSSOM。以防万一有人想知道。
  • 这应该是答案。我的回答比你的得分高一倍,我感到很惭愧。哦亲爱的哦亲爱的。有人给这个人应得的功劳!
  • 这篇文章都是关于解析的,我希望那里的性能影响为零。解析器很快。问题是,在渲染过程中,当浏览器搜索与特定元素匹配的 CSS 声明时会怎样?没有!important规则特别优化的常见情况?我不这么认为,但很难确定; Firefox 中的 layout/style 目录是 80,000 行代码。
  • 您检查确切来源并分享这种高水平知识的努力简直非同寻常且令人惊叹。像您这样的人使 StackOverflow 如此受欢迎和值得信赖。非常感谢您回答和分享这个问题。
【解决方案2】:

我不认为!important 在浏览器匹配规则的速度方面天生就不好(它不是选择器的一部分,只是声明的一部分)

但是,如前所述,它会降低代码的可维护性,因此可能会由于未来的变化而导致代码不必要地增长。使用!important 也可能会降低开发人员的性能。

如果你是真的挑剔,你也可以说!important 为你的 CSS 文件增加了 11 个额外的字节,这不是很多,但我想如果你有相当多的!importants 在你的样式表中可以加起来。

只是我的想法,很遗憾,我找不到任何关于 !important 如何影响性能的基准。

【讨论】:

  • "11 extra bytes" 给或取几个字节用于可选的空格哦,天哪,空格
  • 我知道...我只是在取笑人们在表现方面是多么的挑剔,将这种挑剔提升到一个新的水平。
  • 如果您真的很挑剔,那么以正确的方式进行操作所需的额外特异性通常远远超过 11 个字节。
  • @DisgruntledGoat:头脑清醒的人会意识到浪费的不是字节,而是秒、分钟、小时、天和神经元。 (为什么我还在这里?)
【解决方案3】:

!important 有它的位置。相信我。它救了我很多次,而且通常作为短期解决方案更有用,然后才能找到解决问题的更长、更优雅的方法。

但是,与大多数事情一样,它被滥用了,但无需担心“性能”。我敢打赌,一个小的 1x1 GIF 在网页上的性能影响比 !important 更大。

如果你想优化你的页面,还有更多!important 路线可供选择;) ;)

【讨论】:

  • 这只是一个有趣的结局,让我们都微笑,然后……放松!
  • 什么驴?我必须知道!
  • @Oscar Broman 我认为他的意思是:) :) 看起来像是人体解剖学的一个特定部分,与英语中驴的另一个名称共享一个通用名称。 “The donkey or ass”——这是维基百科关于驴、赦免、驴的文章的开头。我认为 Jan Dvorak 先生和两个支持者属于那种被几乎每一个字(或笑脸)冒犯的人,甚至是远程(或在这种情况下是虚构的)冒犯性的。然而,当你的意思是驴子时说驴子是非常愚蠢和不礼貌的,因为很少会说英语的人能理解它。
  • @DimitarSlavchev Jan 不是在谈论笑脸。请参阅initial version of Michael's post(修订版 2)。
  • @andytuba tbh,它使 Dimitars 的论点无效,但不是他的观点:):)
【解决方案4】:

在幕后发生的事情是,当您的 CSS 被处理时,浏览器读取它,遇到 !important 属性,然后浏览器返回应用 !important 定义的样式。这个额外的过程可能看起来像是一个额外的小步骤,但如果您要处理许多请求,那么您的性能就会受到影响。 (Source)

在你的 CSS 中使用 !important 通常意味着开发者自恋、自私或懒惰。尊重即将到来的开发者...

开发者在使用!important时的思考:

  1. 我的摇摆 CSS 无法正常工作...grrrrr。
  2. 我现在该怎么办??
  3. 然后!important 是的....现在它工作正常。

但是,仅仅因为我们没有很好地管理 CSS,所以使用 !important 并不是一个好方法。它产生了许多设计问题——比性能问题更糟糕——但它也迫使我们使用许多额外的代码行,因为我们用!important 覆盖了其他属性,并且我们的 CSS 变得混乱无用的代码。我们应该做的是先把 CSS 管理好,不要让属性相互覆盖。

我们可以使用!important。但要谨慎使用,只有在没有其他出路时才使用。

【讨论】:

  • 哪种方法更好? css 中的特殊性以确保元素被应用它是正确的样式(这可能意味着一个巨大的 css 语句;例如#news .article .article-title h3 a {})或只是添加重要的标签?
  • @DennisMartinez 最好为标题链接创建一个类并添加这个..
  • 不,只是懒惰。得到坚持。命中。
  • 我不认为 casperOne 删除图像只是因为它们加载缓慢...
【解决方案5】:

我同意您不使用它的观点,因为无论性能如何,这是一种不好的做法。仅基于这些理由,我会尽可能避免使用!important

但在性能问题上:不,不应该引起注意。它可能会产生一些影响,但它应该非常小,您永远不会注意到它,也不应该担心它。

如果它的重要性足以引起注意,那么您的代码中可能存在比!important 更大的问题。简单地使用您正在使用的核心语言的普通语法元素永远不会成为性能问题。

让我用一个反问来回答你的问题;一个你可能没有考虑过的角度:你指的是哪个浏览器?

显然,每个浏览器都有自己的渲染引擎,并有自己的优化。所以现在的问题变成了:每个浏览器的性能影响是什么?也许!important 在一种浏览器中表现不佳,但在另一种浏览器中表现良好?也许在下一个版本中,情况会相反?

我想我的意思是,作为 Web 开发人员,我们不应该考虑(或需要考虑)我们正在使用的语言的单个语法结构对性能的影响。我们应该使用这些语法结构,因为它们是实现我们想要做的事情的正确方法,而不是因为它们的执行方式。

性能问题应结合使用分析器来分析系统中的关键点。首先解决真正让你慢下来的事情。在您深入到单个 CSS 结构之前,几乎可以肯定有更大的问题需要您解决。

【讨论】:

  • 很好的推理。我知道这不值得优化,但我只是好奇。
【解决方案6】:

它不会明显影响性能。但是,它确实会降低代码的可维护性,因此从长远来看可能会降低性能。

【讨论】:

  • @Jan Dvorak 你有什么问题?
  • @BoltClock 我指的是第一句话。
  • @Enve 我的问题是我希望看到一个基准,而不是作为事实呈现的先验假设。我不知道这是哪一个。
  • 我认为它使您的代码更难维护的事实应该足以证明不使用它。我从未经历过任何性能下降,即使与其他较小的性能增强(例如使用 ID 而不是 CLASS 选择器)相比也是如此。
【解决方案7】:

之前我曾多次使用!important,我个人注意到使用它时没有明显的性能损失。

请注意,请参阅the answer to this stack question,因为您可能想使用!important

我还要提一些其他人都没有提到的东西。 !important 是重写内联 css 的唯一方法,而不是编写一个 javascript 函数(即使只是一点点也会影响你的性能)。因此,如果您需要覆盖内联 css,它实际上可以节省一些性能时间。

【讨论】:

    【解决方案8】:

    嗯... !important 还是 !!important?

    让我们一步一步来:

    1. 解析器必须检查每个属性的 !important,无论您是否使用它 - 所以这里的性能差异是 0
    2. 覆盖属性时,解析器必须检查被覆盖的属性是否 !important - 所以这里的性能差异再次为 0
    3. 如果被覆盖的属性是 !!important,它必须覆盖该属性 - 不使用 !important 的性能损失为 -1
    4. 如果被覆盖的属性是 !important,它会跳过覆盖该属性 - 使用 !important 的性能提升 +1
    5. 如果新属性是 !important,无论被覆盖的属性是 !important 还是 !!important - 性能差异再次为 0,解析都必须覆盖它

    所以我猜 !important 实际上具有更好的性能,因为它可以帮助解析器跳过许多其他情况下不会跳过的属性。

    正如@ryan 在下面提到的,唯一的方法是覆盖内联 css 并避免使用 javascript...所以另一种方法可以避免不必要的性能损失

    嗯...原来 !important 很重要

    还有,

    • 使用 !important 可为开发人员节省大量时间
    • 有时可以让您免于重新设计整个 css
    • 有时 html 或父 css 文件不在您的控制范围内,因此它可以挽救您的生命
    • 明显防止 !important 元素被其他 !!important 元素意外覆盖
    • 有时浏览器只是没有选择正确的属性,没有在选择器中过于具体,所以使用 !important 确实变得很重要,并且可以让您免于在 css 中编写大量特定的 css 选择器。所以我想即使您使用更多字节来编写!important,它也可以在其他地方为您节省字节。我们都知道,css 选择器会变得很乱。

    所以我想使用 !important 可以让开发者开心,我认为这非常重要 :D

    【讨论】:

    • “所以我猜 !important 实际上具有更好的性能,因为它可以帮助解析器跳过许多其他情况下不会跳过的属性。”一旦您有多个 !important 声明,此声明将立即无效。浏览器必须检查所有这些。所以它真的回到了第 1 步。
    • @BoltClock 无论您使用多少次,解析器都必须检查该属性...因此,如果您有 10 个属性,解析器必须进行 10 次检查,无论这些属性是否是!重要与否。所以如果你有 10 个 !important 属性,解析器会进行 10 次检查,如果你有 10 个 not !important 属性,解析器仍然会进行 10 次检查...有意义吗?
    • 仍然不确定 !important 是否是性能提升,真的......但我非常享受所有 cmets 和讨论。我的知识正在向前迈出下一步。 StackOverflow 真是太棒了:D
    【解决方案9】:

    我无法预见!important 会阻碍性能,无论如何都不会。但是,如果您的 CSS 中充满了!important,则表明您已经过度限定选择器并且过于具体,并且您已经用完了父母或限定符来增加特异性。因此,您的 CSS 会变得臃肿(影响性能)并且难以维护。

    如果您想编写高效的 CSS,那么您希望 尽可能具体,并编写 modular CSS。建议不要使用 ID(带有哈希)、链接选择器或限定选择器。

    在 CSS 中以 # 为前缀的 ID 非常具体,以至于 255 classes won't override an id(小提琴:@Faust)。 ID 也有更深层次的路由问题,它们必须是唯一的,这意味着您不能将它们重复用于重复样式,因此您最终会编写具有重复样式的线性 css。这样做的影响会因项目而异,具体取决于规模,但可维护性将受到极大影响,在极端情况下,性能也会受到影响。

    如何在没有!important、链接、限定或 ID(即 #)的情况下添加特异性

    HTML

    <div class="eg1-foo">
        <p class="eg1-bar">foobar</p>
    </div>
    <div id="eg2-foo">
        <p id="eg2-bar">foobar</p>
    </div>
    <div class="eg3-foo">
        <p class="eg3-foo">foobar</p>
    </div>
    

    CSS

    .eg1-foo {
        color: blue;
    }
    .eg1-bar {
        color: red;
    }
    [id='eg2-foo'] {
        color: blue;
    }
    [id='eg2-bar'] {
        color: red;
    }
    .eg3-foo {
        color: blue;
    }
    .eg3-foo.eg3-foo {
        color: red;
    }
    

    JSFiddle

    好的,那它是如何工作的?

    第一个和第二个例子的工作方式相同,第一个实际上是一个类,第二个是属性选择器。类和属性选择器具有相同的特性。 .eg1/2-bar 不会从 .eg1/2-foo 继承其颜色,因为它有自己的规则。

    第三个示例看起来像是限定或链接选择器,但两者都不是。链接是当您在选择器前面加上父母、祖先等时;这增加了特异性。限定是类似的,但你定义了选择器应用到的元素。排位赛:ul.class 和链接:ul .class

    我不确定你会如何称呼这种技术,但这种行为是故意的,并且是 documented by W3C

    允许重复出现相同的简单选择器,并且 确实增加特异性。

    当两条规则的特异性相同时会发生什么?

    作为@BoltClock pointed out,如果有多个 !important 声明,那么 规范规定最具体的应该优先。

    在下面的示例中,.foo.bar 具有相同的特异性,因此行为回退到 CSS 的级联性质,即 CSS 中声明的最后一条规则声明优先级,即 .foo

    HTML

    <div>
        <p class="foo bar">foobar</p>
    </div>
    

    CSS

    .bar {
        color: blue !important;
    }
    .foo {
        color: red !important;
    }
    

    JSFiddle

    【讨论】:

      猜你喜欢
      • 2020-10-26
      • 2012-01-20
      • 2011-10-13
      • 2011-11-24
      • 2013-07-26
      • 2010-09-18
      • 1970-01-01
      • 2010-12-17
      • 1970-01-01
      相关资源
      最近更新 更多