CSS 特异性过滤器

Posted

技术标签:

【中文标题】CSS 特异性过滤器【英文标题】:CSS Specificity Filter 【发布时间】:2012-08-04 04:24:38 【问题描述】:

这是一个长镜头,但是否有可用的工具通过删除不需要的特异性来优化 CSS 选择器?

我发现当我写 CSS 时,我故意让我的选择器比必要的更具体,以避免冲突和准文档。

如果有一种工具可以分析给定的一组规则,确定它们与其他规则重叠的“唯一性”,然后去除任何不必要的特殊性,那就太好了。

我什至无法想象工具开发人员会如何处理这需要的所有场景,但我之前曾被其他人在该领域的独创性所震撼,并认为值得一问。

更新:

我在这个问题上加了一个赏金,我越想它,我就越意识到 的价值。

例如,在Sass 和LESS 中使用嵌套规则/选择器时,过度嵌套 是common 和well-known 反模式,很容易导致选择器过于具体。

在优秀的 TutsPlus 课程Maintainable CSS with Sass and Compass中有一个很好的说明:

body 
    div.container 
        p 
            a 
                color: purple;
            
        
    

Sass 将遵循这些嵌套指令并生成以下 CSS 输出,不会对任何不必要的特殊性提出异议:

body div.container p a 
    color: purple;

但是,如果存在/确实存在特异性过滤器,它将为 CSS 开发人员带来潜在的好处:

    您可以将样式表组织为 DOM 的 1:1 映射,类似于您在 Firebug 和 Chrome 开发工具中检查样式规则时看到的内容。智能编辑器/IDE 可以为具有共享样式/类的 DOM 元素自动填充样式。当然,这种冗余会被特异性过滤器/优化器过滤掉。

    样式表的结构可以由扫描 DOM 并将其转换为 CSS 选择器/规则的工具预先填充。这意味着开发人员只需要更新 html; CSS“树”将保持同步以反映 DOM 的当前状态。智能编辑器可以让您跳转到元素/类的 CSS 定义以进行样式设置——甚至可以在单独的面板中显示其样式规则。

在某种程度上,这似乎是一种倒退——就像您在 Dreamweaver 或 WebAssist 中发现的帮助新手学习 CSS 的功能一样。但是 CSS 选择器优化工具的基本思想似乎很简单,我所描述的工作流自动化类型将是合乎逻辑的下一步——催化剂将是特异性过滤器。

我研究了一些更知名的 CSS 编辑器和 Web IDE,但除了定位单个元素并为其生成选择器之外,没有发现任何提供此类功能的东西。

更新 2:CSS 选择器性能

针对 Spliff 的评论,这里有两篇关于 CSS 选择器性能的精彩文章:

Performance Impact of CSS Selectors史蒂夫·苏德斯

Efficiently Rendering CSS by Chris Coyier

两者都同意微优化 CSS 不值得努力,但过度限定的后代选择器是“效率灾难”。我自己还没有进行基准测试,但我怀疑我建议的那种“DOM 映射”方法会在没有手动或自动优化步骤的情况下导致性能下降。

相关问题、链接和工具:

Points in CSS Specificity

Tool to See CSS Specificity

Tool for Cleaning Up CSS

Order by CSS Specificity

Top 5 Mistakes of Massive CSS

Google: Efficient CSS Selectors

Procssor

Clean CSS

CSS Tidy

【问题讨论】:

当然,这样的工具需要检查 DOM 或页面以作为样式表的基础并做出正确的观察/假设(例如,是否只有一个带有 @ 的 header 元素987654341@? aside 元素是否只会出现在 section.sidebar?) 中。否则,在不从根本上改变选择器含义的情况下,从选择器中去除特异性的唯一方法是删除重复的简单选择器,(例如,section > div.foo.foo:nth-of-type(odd) 变为 section > div.foo:nth-of-type(odd))。 @BoltClock:另外,如果遇到 ID,通常可以安全地消除它之前的任何内容。 html body div p#lorem span 通常可以缩写为 #lorem span 老实说,除了遵循一些简单的规则(不要将元素添加到 id/class 选择器中,不要对嵌套感到疯狂等),我认为这不值得担心关于。这几天browser vendors are optimizing for this。 这就是为什么我一开始不使用预处理器... @Truth 它也不一定适用于动态生成的 HTML。在这种情况下,实际元素和嵌套可能取决于上下文,并且您可能只想将样式应用于该 ID,如果它在该特定上下文中遇到(它周围的元素)。但问题本身也有同样的问题。具有生成 HTML(无论是服务器端还是客户端)的高度动态页面将难以编写可靠工作的过滤器。 【参考方案1】:

您可以尝试采用不同的方法,尝试将选择器编写得尽可能小(低特异性)。并且仅在需要时使它们更加具体。 使用这种工作方式,您不需要工具。

【讨论】:

Writing efficient CSS selectors 感谢您的回复,但整个想法是避免这种方法——拥有一个允许我们编写 CSS 而无需考虑特殊性的工具。现在的工作方式是,我们必须跨多个规则设置 DOM 元素的样式——优化工具将允许我们在一个地方处理元素的所有样式。在我看来,这是一个更合乎逻辑的工作流程;我们只是对 CSS 不能以这种方式工作的事实感到麻木。 CSS 是一种“基于情境”的语言(取决于 HTML),没有全方位的 CSS 编码,否则每个人都可以做 CSS 样式。特异性是如此重要,如果有人不理解特异性,他/她肯定会写出糟糕的 CSS。我从未有过拥有工具的冲动。一个工具永远不能像你想要的那样输出代码(又名读心软件)。 CSS(面向对象)是你必须掌握的东西,就像任何其他网络语言一样。【参考方案2】:

只是把它扔在那里——它不会“回答”你的问题,但它是我喜欢向从事大量 css 编程的人宣传的工具:Firebug。强>

如果您不熟悉它,它是一个用于网络浏览器的工具。安装后拉出页面,右键单击并选择“检查元素”。它将向您展示影响页面上不同元素的所有 css,并且对于创建干净、精确的 css 代码很有用。此外,只需稍作修改,即可更轻松地查看页面外观的即时更新。 它会通知您被其他 css 代码覆盖的无用 css 代码。

还有! Firebug 现在几乎可用于所有浏览器。不仅仅是火狐。就个人而言,我偏爱在 Chrome 中使用它。

【讨论】:

谢谢,我同意 Firefox 是一个很棒的工具。【参考方案3】:

我们真的不能没有特异性,因为当您有两个或多个规则发生冲突时,它是唯一可以拯救您的方法。特殊性为整个混乱的 CSS 规则带来了理智,因此它更像是一种祝福而不是诅咒。你谈到的一些东西,比如 CSS 选择器,可以使用 Firefox/Firebug 来完成。我更担心浏览器的兼容性。

【讨论】:

我的想法和我在帖子中提到的完全一样——如果你想确保你写的 CSS 很好,Firebug 很棒。 您是否提前点击了提交?你的最后一句话不完整。【参考方案4】:

实际上有一种方法可以使用 HTML5 和 CSS3 来实现。标准技术是使用 HTML 5 属性 "data-" 指定元素,然后为此属性进行 CSS 选择。这不是属性的目的,但您可以自定义指定一些元素,您甚至可以使用这些元素来切换站点的主题。

因此,例如,您最终可以通过指定在 CSS 中手动创建特异性过滤器

<b data-specificity=2>test</b>

其中数据特异性仅与上述父项匹配。

更新:

好的,例如,假设您有一个段落类,但您想指定段落可以从哪个父级或多少个父级继承属性。您将为每个可以继承自的潜在父母使用规则:

p[data-specificity="1"]
    color:red;
    font-family:verdana;
    text-decoration:underline;

p[data-specificity="2"]
    color:black;
    font-family:arial;

div.container > *[data-specificity="2"] 
    font-family:impact;
    color:blue;
    text-decoration:underline;

因此这些规则意味着任何作为 div 容器的直接子级且具有特异性 2 的 p 标签都可以从 div 容器继承属性。 div 的蓝色被具有数据特异性 2 的 p 继承。

这是JSFiddle,您可以在其中看到这个!

这样的想法是,使用 HTML5,您可以准确控制允许哪些元素继承哪些属性。需要编写大量额外代码(针对子元素和父元素),但您可以使用它来消除一些不必要的特殊性

我从来没有真正看到有人在实践中使用过这种方法,我几乎只是为你准备了它,但我认为它可能非常有用,你觉得呢?

【讨论】:

这是一个有趣的方法,感谢您的回复。不幸的是,所需的非语义标记的数量对我来说是一个交易杀手,但这是一个非常有创意的解决方案。 好吧,我不能在接下来的几个小时内给出一个好的答案,但是如果你以某种方式延长赏金日期,我会发布一个非常干净的解决方案和示例代码 ;) 当然,我很高兴重新获得赏金(假设这是允许的)。当我这样做时,我会在此处添加评论,以便它出现在您的收件箱中。 抱歉,更新了我的答案。当我写下答案时,我想到了别的东西。我相应地编辑了答案

以上是关于CSS 特异性过滤器的主要内容,如果未能解决你的问题,请参考以下文章

各向异性过滤有啥用?

opengl 三线性和各项异性过滤

如何使各向异性过滤扩展工作?

sdl2 opengl d3d9的mipmap和各项异性过滤渲染

Mipmap导致模型黑色接缝问题。

Firefox 的 CSS 过滤器替代品是啥?