在 CSS Lint 中,他们不建议使用 id
来选择元素。我相信 CSS Lint,因为它是由非常了解 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
。<div class="foo">
内的所有<a>
元素,请使用.foo a
。<div id="bar">
内的所有<a>
元素,则使用#bar a
是有意义的。然而,你也可以使用更低优先级的选择器。 [id="bar"] a
与 .foo a
具有相同的优先级,这意味着你仍然可以通过 ID 针对特定元素进行选择,而不会创建具有不必要高优先级的选择器。[id="XXXX"]
选择器来基于[id]
属性选择,因为它很啰嗦并且可能会导致混淆。我建议使用[data-id="XXXX"]
选择器来基于自定义的[data-*]
属性选择样式,以更紧密地关联样式与 DOM 节点的当前状态。CSSLint提供了为什么推荐使用类而不是id选择器的指南:
不应在选择器中使用ID,因为这些规则与HTML紧密耦合且无法重用。更好的做法是在选择器中使用类,并将类应用于页面上的元素。此外,ID会影响您的特异性并可能导致特异性冲突。
(来自禁止在选择器中使用ID的文档。)
基本上,如果你将代码结构化为使用类而不是ID,则你的代码可以变得更加通用和可重用,这通常是一件好事。此外,特异性是一个难以理解的问题,可能会导致难以找到的错误,如果省略ID选择器,则较少出现意外解析冲突的情况。
首先:
CSS Lint和JS Lint一样,是一种伪装成验证的观点,而不是权威。
我在这个领域已经工作了五年。我曾在大型零售网站、互动代理机构以及作为独立承包商工作,并目前在一家SaaS公司工作。
我认为,ID无可非议地是坏的想法,只有当你处理团队时的CSS-fu并不好时,你才会得出这个想法。
在我看来,良好、灵活的CSS应该遵循以下 一般 的最佳实践:
始终从一般到特定。例如,对于通用正文文本的字体系列和最常见的字体大小,应该只在一个地方声明。随着您上升到更典型地涉及类使用的选择器,您将开始覆盖字体大小。当需要将一个基本不使用的字体系列应用于非常特定的HTML子集时,使用ID命中获取正文文本变化的元素就有意义了。
属性越普遍应用,越容易被覆盖,您永远不应该担心意外覆盖最常用的属性。例如,body#some_id div
,由于这个原因是一个非常糟糕的选择器。在第二层(大概有三层),您通常处理与类容器相关联的通常重复使用元素的捆绑包时,意外发生更频繁,这时覆盖这些属性应该会更难一些。在最后一层,您不应该使用可重用元素,而是针对文档高度特定部分的覆盖。在这种情况下,使用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文件中出现巨大的、不可预测的混乱。
因此:尽量不要使用多个ID,仅用于容器本身局部的属性,而且不包含其他容器。尽量不要使用超过一个或两个类。避免针对高层元素(它们所代表的容器往往是许多祖先节点之上)的类和ID。除非进行维护或培训/惩罚新手,否则大多数情况下超过3-4个标记可能太多了。遵循童子军规则。在安全时随时清除那些重要的和明显过于具体的选择器。
但是,请坚持经验法则而不是CSS“规律”,并确保在实践中评估这些想法。不要相信任何人或任何工具发表像“永远不要使用ID”这样的笼统陈述,因为CSS布局方案有很多变量。就我而言,这只是新手才会干的事情,作者如果想要声称自己是专家,那么应该懂得更好的做法。
body .main-content .side-bar .sub-nav > ul > li > button
这样的规则。通过将适用深度保持在2级,不使用ID或元素进行样式设置,可以避免具有极高特定性的选择器争夺问题。有例外吗?是的。但如果你真正组织好你的选择器,就不会出现这种垃圾选择器。 - Scott Silvi#second_div
或#a_tag_named_kevin
。那么#overlay_container
呢?当您将其作为类看待时,您是否确定它可能是每个页面上唯一的弹出式容器,可以在Web应用程序的每个页面上交换内容?哪种方法更具语义,并为我提供有关该元素在布局中可能扮演的角色的更多信息?如果我想要更改大型应用程序中的#overlay_container > .standard_headline
与类版本之间的区别,我可以获得多少关于意图和布局影响范围的确定性? - Erik Reppen组件:如果您编写可重复使用的组件,例如带有 ID 的表格(例如 <div id="data">
),那么如果您将两个表格放入同一文档中,则会得到 INVALID HTML。