为什么CSS不推荐按ID选择



在CSS Lint中,他们不建议使用id来选择元素。我信任CSS Lint,因为它是由非常了解CSS的聪明人编写的。但是我想知道的原因是什么呢?为什么选择一个id不是一件好事?

我不同意从不使用id来选择元素的想法,但是我确实理解其中的原因。

通常情况下,当一般形式已经足够时,开发人员会使用一个非常高特异性的选择器:

#foo #bar #baz .something a {
text-decoration: underline;
}

最好写成

.something a {
text-decoration: underline;
}

此外,书写风格如:

#foo-1,
#foo-2,
#foo-3,
#foo-4 {
color: #F00;
}

最好写成:

.foo {
color: #F00;
}

我与CSSLint的不同之处在于结构id被重用。

我经常用这样的结构来标记页面:

<div id="page">
<div id="page-inner">
<header id="header">
<div id="header-inner"></div>
</header>
<nav id="nav">
<div id="nav-inner"></div>
</nav>
<div id="wrapper">
<div id="wrapper-inner">
<div id="content">
<div id="content-inner">
<article></article>
...
</div>
</div>
<div id="sidebar">
<div id="sidebar-inner">
<div class="module"></div>
...
</div>
</div>
</div>
</div>
<footer id="footer">
<div id="footer-inner"></div>
</footer>
</div>
</div>

因为我知道结构是一致的,我不介意在我的css中使用#page,#header,#nav,#wrapper,#content,#sidebar#footer来扫描特定区域的样式。这些样式紧密耦合这使得的可重用性降低;因为我重用结构,所以它们可重用的。重要的是要记住,在选择器中使用ID是非常特定的,应该谨慎使用。


关于特异性的几句话:

一般来说,应该使用尽可能低的特异性选择器来做出正确的选择:

如果你的目标是所有<a>元素,那么使用a是有意义的。
如果你的目标是所有<a>元素在<div class="foo">中,那么使用.foo a是有意义的。
如果你的目标是所有<a>元素在<div id="bar">中,那么使用#bar a是有意义的。然而,您可以使用较低特异性的选择器。[id="bar"] a.foo a具有相同的特异性,这意味着您仍然可以通过ID针对特定元素,而无需创建不必要的高特异性选择器。

Ido not通常建议使用[id="XXXX"]选择器来选择[id]属性,因为它冗长且可能导致混淆。我建议使用[data-id="XXXX"]选择器根据自定义[data-*]属性进行选择,以更紧密地将样式与DOM节点的当前状态联系起来。

CSSLint给出了一个指南,说明他们为什么会提出这样的建议:

id不应该在选择器中使用,因为这些规则与HTML耦合得太紧,没有重用的可能。更可取的做法是在选择器中使用类,然后将类应用于页面中的元素。此外,id会影响您的专用性,并可能导致专用性战争。

(From Disallow id in selector .)

基本上,如果你的代码结构使用类而不是id,你的代码可以更通用和可重用,这通常是一件好事。此外,专一性是一件很难理解的事情,并且可能导致难以发现的错误,因此,如果省略ID选择器,就不太可能以意想不到的方式解决冲突规则。

首先:

CSS Lint,像JS Lint一样,是伪装成验证的意见,而不是权威。

我干这行已经五年了。我曾在大型零售网站工作过,在互动机构工作过,担任过独立承包商,目前在一家软件即服务公司工作。

id绝对是糟糕的想法,在我看来,只有当你的CSS-fu在处理团队时不是那么好时,你才会有这样的想法。

好的,灵活的CSS, IMO,遵循以下一般最佳实践:
  • 始终从一般移动到特定. 例如,一般正文文本的Font-family和最常见的font-size应该只在一个地方声明。当您移动到通常涉及使用类的选择器时,您将开始覆盖font-size。当需要将大多数未使用的字体族应用于非常特定的HTML子集时,在容器上使用ID来命中获得正文文本变化的元素是有意义的。

  • 一个属性应用得越广泛,就越容易重写您不应该担心意外地覆盖了最通用的属性。例如,body#some_id div是一个非常糟糕的选择器。在第二层(大约有3层),您通常更多地处理绑定到分类容器的常见重用元素束,因此意外地覆盖这些属性应该稍微困难一些。在我看来,当你到处都是多类选择器时,"意外"会更频繁地发生。在最后一层,您不应该处理可重用的元素,而应该处理文档中高度特定部分的覆盖。在这些情况下使用ID是一种理想的做法,而不是糟糕的做法,但ID最好是有节制地使用,并且只用于项目容器中需要更改ID的元素的特定属性。

  • 选择器越具体,就越难被意外破坏。这里的特定并不仅仅是指元素上的id。我的意思是一个有ID的容器元素,它位于您实际定位的元素附近。然而,有意的重写应该总是涉及最少的工作,这是id实际上帮助而不是阻碍您的地方(参见下面的示例)。如果你发现自己处于"用完id、类和标签"的境地,我建议你使用暴力(至少是想象中的暴力)。但是说真的,有人应该被打。

  • 避免冗长的选择器列表:你应该开始觉得你"做错了",每当你经常使用4+选择器值的声明。在计数时,我不会将>作为标记/值,因为明智地使用它对于可维护性和性能都是一个极好的实践。

  • 避免特定军备竞赛:你认识他。这个"不要乱动我的东西"的菜鸟决定用所有的标签、选择器和ID来掩盖自己的屁股,从身体开始。别雇那家伙,也别打他屁股,直到他停止。但即使在更有前瞻性的团队中,如果你不(有节制地)在有意义的地方增加选择器的权重,军备竞赛仍然可能开始。

极简主义方法尤其巨大。您越是依赖HTML的位置来避免首先需要CSS,效果就越好。您在全局分布最通用的样式方面做得越好,在更具体的上下文中需要担心的问题就越少。越精确的目标和简洁的高度特定的属性重写,它们就越容易长期管理。在我看来,这就是无id政策愚蠢的地方。

什么更实用,更直接的重写?

:

body .main-content .side-bar .sub-nav > ul > li > button

还是这个?

#sub-nav button

如果你通常独自工作或只做小项目,以保持做web开发谋生的外表,同时在演讲中赚到真正的钱,上面的一个可能看起来很傻,不太可能,但当你与一个团队合作,你遵循一个类唯一的政策,你刚刚因为最近没有使用足够高的专用性而被烧伤。很容易开始添加越来越多的类和标签到你的东西中(只是为了避免在短时间内遇到麻烦-当然你稍后会改回来),导致你的CSS文件中出现巨大的不可预测的混乱。

So:尽量不要使用多个ID,并且仅用于不包含其他容器的容器的本地属性。尽量不要使用超过一个或两个类。避免以上层元素为目标的类和id(它们所代表的容器是上面的许多祖先节点)。在大多数情况下,超过3-4个标签可能太多了,除非是时候进行一些维护或训练/打屁股的新秀。遵循童子军规则。在安全的情况下,删除那些重要的和明显过于特定的选择器

但是要坚持经验法则而不是CSS"法则",并确保你根据经验来评估这些想法。不要相信任何人或任何工具,他们会对CSS布局场景中尽可能多的变量说"永远不要使用id"。在我看来,这只是菜鸟的口头语,如果作者想自称是这方面的专家,他们现在应该知道得更好了。

lonessomeday在他们的回答中提到了他们的论点,即它与HTML紧密耦合并且不允许重用。

我可以提出一个论点,在某些情况下,你不希望一个样式被单个元素以外的任何东西使用,所以在id选择器上指定它是有意义的。

这一切都取决于个人喜好。这不是你必须遵守的硬性规则,这似乎是CSS Lint团队的想法,而不是导致错误或其他事情的规则。

当你管理大量的CSS或大型网站时,一个大问题就出现了。根据定义,id是不可重用的。但你也会遇到特殊性的问题。当你开始改变专一性时,你就会进入令人讨厌的比赛状态。id比类有更多的特殊性,但是内联样式比id有更多的特殊性。内联样式比外部样式表具有更多的特殊性。通过使用类,您可以标准化如何将样式应用于元素,从而使事情更可预测。这倾向于简化开发,特别是当与多人一起工作时。

COMPONENTS:如果你写可重用的组件,例如表与id(例如<div id="data">),那么如果你把两个表到一个文档,那么你会得到无效的html。

最新更新