CSS 标记限定(例如 h1.some-class)有啥问题?
Posted
技术标签:
【中文标题】CSS 标记限定(例如 h1.some-class)有啥问题?【英文标题】:What's wrong with CSS tag qualifying (e.g. h1.some-class)?CSS 标记限定(例如 h1.some-class)有什么问题? 【发布时间】:2016-10-22 13:41:19 【问题描述】:有人可以向我解释为什么标签限定是一种不好的 CSS 做法吗?为什么 tag.class 在具有自我解释的元素的情况下不好? 例如
<section class="carousel-item">
<header class="header of-carousel">
<h2 class="heading of-carousel">Services</h2>
</header>
…
<footer class="footer of-carousel">
…
</footer>
</section>
为什么它应该比带有上下文修饰符的 DRY 和简洁的代码更好?
<section class="carousel-item">
<header class="of-carousel">
<h2 class="of-carousel">Services</h2>
</header>
…
<footer class="of-carousel">
…
</footer>
</section>
.of-carousel
header.& …
h2.& …
footer.& …
甚至
section.carousel-item
header
h2
footer
.carousel-item
header …
h2 …
footer …
我看到很多人沉迷于 BEM,但我不明白为什么? 他们的选择器太丑了,尤其是--in-the-HTTP-2__times。
【问题讨论】:
这是因为人们认为 CSS 可以完全从 html 中解耦出来,并且可以跨不同类型的页面重用。 @Bhojendra Nepal:我不这么认为。 如果您希望在任何时候更改下划线 html,它会增加特异性,并使其更难重用(尽管这对于大型代码库来说往往是一个更大的问题)。 @Lee:你确定 h2.of-carousel 比 .header.of-carousel 更具体吗? @BoltClock:.header.of-carousel
比h2.of-carousel
更具体,这比.carousel-header
更具体(这是我个人会使用的),并且如果更改底层html(直接定位元素时)。
【参考方案1】:
您应该避免嵌套,这样可以最大限度地减少其他规则相互冲突的可能性。确保我们的 CSS 模块在任何情况下看起来都一样。
.block__elem--修饰符语法并不难看,如果您不使用多个嵌套元素。
【讨论】:
【参考方案2】:我熟悉的惯例是,如果选择器具有不同程度的特异性,则限定是不好的。也就是说,用类或标签来限定 id(因为 id 已经是唯一的),或者用标签来限定类(因为类应该比标签更独特,如果你的目的是让一个类在两种不同的情况下做两件不同的事情,你应该通过使它们成为两个不同的类来增加可读性)。然而,我从来没有被告知使用 class-on-class 限定符是不好的做法(事实上,我怀疑 Bootstrap 相当广泛地使用这些,纯粹基于它的语法)。
This article from MDN 是“css tag qualifying”的热门搜索结果之一,似乎同意我的观点,至少关于何时这是不好的做法:
如果规则有一个 ID 选择器作为其键选择器,请不要将标签名称添加到规则中。由于 ID 是唯一的,添加标签名称会不必要地减慢匹配过程。
接着说:
前面的概念也适用于[用类来限定标签]。尽管类可以在同一页面上多次使用,但它们仍然比标签更独特。您可以使用的一种约定是在类名中包含标签名称。但是,这可能需要一些灵活性;如果对标签进行设计更改,则类名也必须更改。 (最好选择严格语义的名称,因为这种灵活性是单独样式表的目标之一。)
CSS Tricks 似乎同意,说:
ID 是唯一的,因此它们不需要标签名称。这样做会降低选择器的效率。如果可以避免,也不要使用类名。类不是唯一的,所以理论上你可以让一个类名做一些对多个不同元素有用的事情。如果你想让样式根据元素而有所不同,你可能需要标记限定(例如 li.first),但这非常罕见,所以一般来说,不要。
我希望这有助于回答您的问题。
【讨论】:
是的。我读了很多遍。 tag#id 确实是一件坏事。没有问题。但我还是不明白为什么 tag.class 不好?实际上,在我的实践中,根据元素进行样式设置是很常见的情况。为什么这种需求不如将同一类应用于不同元素的能力重要?我个人比较喜欢,
不喜欢,
和这样的 WET / tautology :) 无论如何,谢谢大家的回答。 @Vladimir 我认为它不好因为它使compute specificity 变得更加困难,而且还因为将语义(段落、标题、代码...)与演示文稿更难维护。如果您要将h2
更改为h3
,则需要同时编辑html 和样式表。如果您的样式表中不提及任何标签,您就不会有这个问题。【参考方案3】:
BEM 背后的原则是删除 CSS 文档中的所有实际层次结构,并为每个要设置样式的元素设置一个明确的规则。这就是它高效的原因——渲染器永远不必遍历 DOM 来处理子规则,或者尝试匹配多个限定符(这就是为什么在类选择器旁边使用标签限定符被认为是“不好的” )。但我同意,BEM 的标准命名约定非常难看。不过,您可以根据自己的喜好进行更改。
您需要了解 CSS 规则是从右到左处理的。以你为例:
.carousel-item
header …
h2 …
footer …
这将导致渲染器首先匹配 all <header>
、<h2>
和 <footer>
元素。通过这些匹配,它会尝试找到匹配的父 .carousel-item
,一直迭代到文档的根目录,直到找到一个。将此样式应用于具有多个 <h2>
和 <header>
元素未包含在 .carousel-item
中的深度嵌套文档将意味着有很多浪费的查找。简单地说:这不是很有效。
您可以通过使用直接子选择器 (>) 来减轻这种影响,因为这样它就不会尝试一直遍历 DOM;它只会尝试第一个父母。 BEM 完全避免了这个问题。
实际上,现在这是一个非常小的问题,与非最佳 CSS 相比,处理客户端 javascript 的 CPU 周期可能更多。但是,如果您要构建大型项目,请牢记这一点。
【讨论】:
如果这就是 BEM 的用途,那为什么还要使用外部 CSS 呢?如果每个元素都有自己的规则,只需使用内联样式。 BEM 用户的需求与 CSS 的意义之间似乎存在一些认知上的不协调。 当然,关于 Yandex 开发人员的原因,我知道“从右到左”和“无嵌套”规则,但在我看来,如果文档包含的 h2 或标题过多,则只是一个糟糕的文件。性能问题可能是由通用元素引起的,例如 div、span、链接和列表项。他们应该在大型项目中进行 BEMed。对于所有其他情况,窄范围和级联看起来是最好的质量/价格比选项。 .some-ui-area h2 /** 您的文档中可以有多少个子标题? 2000?没有。 2-10,对吧? **/ 未来可能出现规则冲突?好的。为所有新的特殊情况创建独特的类。在我看来,它更符合继承、DRY、KISS end 等原则。以上是关于CSS 标记限定(例如 h1.some-class)有啥问题?的主要内容,如果未能解决你的问题,请参考以下文章