一个CSS ID选择器对应多个相同ID元素的情况

17
在一个页面中给多个元素赋予相同的ID是否安全?例如,在使用某些jquery插件时经常会出现这种情况,当您运行两次或更多次滑块或图库时。我们知道,开发人员喜欢为html容器分配一些ID以使脚本运行更快。

让我们阅读w3.org文档

类型为ID的属性之所以特殊是因为没有两个这样的属性可以具有相同的值;无论文档语言如何,ID属性都可以用于唯一标识其元素。

但是下面这个例子中有两个具有相同ID的元素在所有浏览器中都能正常工作,尽管它不是有效的:

#red {
  color: red;
}
<p id="red">I am a red text.</p>
<p id="red">I am a red text too.</p>

有人能解释一下这个奇怪的情况吗?


24
观察发现,长时间在一个页面上使用相同的“ID”属性来表示多个元素会导致自燃和核战争。如果被发现使用多个相同的ID,互联网民兵将立即开枪击毙你。这是你能做的最不安全的事情之一。 - zzzzBov
5
我每月可以更改一次代码,这样他们就找不到我了 :) - Arsen K.
从你的问题中并不清楚你是指CSS中的多个ID选择器,还是HTML页面中相同ID的多个副本。实际上,你似乎在这里问了两个完全不同的问题。 - BoltClock
为什么不清楚呢?在我的例子中,我写了两个带有相同ID的段落标签。所以我的意思是“HTML页面中有多个相同ID的副本”。 - Arsen K.
1
你的问题标题说“几个ID选择器”,这可能有点令人困惑。我已经为您修复了它。我还为了完整性扩展了我的答案。 - BoltClock
3个回答

35

浏览器总是试图“静默失败”。这意味着,即使您的HTML无效,浏览器也会尝试猜测您的意图,并相应地处理。

然而,偏离规范可能会导致一些非常不可预见的副作用。

例如:

document.getElementById('red');

使用这种方式只能获取第一个元素。

此外,为了确保代码按预期工作,您还必须在所有用户可能使用的浏览器中测试页面。您不能仅仅假设它会正常工作。

简而言之:不要这样做!如果您需要针对多个元素使用相同的CSS,请使用类名。那就是它们的设计目的...


话虽如此; 如果你确实需要选择多个具有相同ID的元素,请使用属性选择器:

document.querySelectorAll('p[id="red"]');

需要注意的是,这在IE7及以下版本无法工作...


1
当然,即使在我最糟糕的噩梦中,我也不会这样做。 :) 当我写“所有浏览器”时,我指的是5个主要浏览器:FF,Opera,Chrome,Safari和IE。 - Arsen K.
2
@Webars:将其扩展到... IE6,IE7,IE8,IE9,IE10 ;) - Joseph Silber
1
作为一个快速提示,document.querySelectorAll('p#id')实际上与CSS中的p#id行为相同,因为它使用浏览器本地的CSS选择器实现。当然,仍然存在这样的情况,即您不应该将多个元素分配相同的ID。 - BoltClock

7
在一个页面中给多个元素赋予相同的ID是不符合验证规则的。但是,规则总是会被打破,在HTML标签混乱的世界里,浏览器必须考虑到这些破坏规则的情况,而不破坏页面,这就是你所观察到的行为。
虽然已经证明了即使这样做,浏览器的行为也是一致的(幸运的是,在无法避免的情况下),但我不会完全认为这样做是“安全”的,因为这种行为可能不一致或不可靠。
最好的方法是尽可能忠实地遵循规则,并仅在有非常非常好的理由时才违反规则(而你几乎永远不会,所以甚至不要考虑)。否则,像Joseph Silber所说的那样,使用类,专门用于对多个元素进行分类或分组。
在HTML文档中,ID的唯一性不受CSS强制执行或假定;相反,选择器规范只是简单地陈述了这一点:
一个ID选择器表示具有与ID选择器中的标识符匹配的标识符的元素实例。
注意在这个句子中使用了“an”这个词。
在该语句之后是一些示例用法,这些用法使用了单词“any”。

The following ID selector represents any element whose ID-typed attribute has the value "chapter1":

#chapter1

The following selector represents any element whose ID-typed attribute has the value "z98y".

*#z98y
在选择器规范的第三级中,该规范澄清了符合文档的假设(强调属于我的一部分):ID 类型属性的特殊之处在于,在符合文档的情况下,无论携带它们的元素类型如何,不会有两个这样的属性具有相同的值;无论文档语言如何,可以使用 ID 类型属性来唯一标识其元素。"符合文档"指符合 HTML 而非 CSS 规范。请注意,这段文字并非规范性内容。尽管这是帮助实现者解决错误处理案例的一种方式,但它不是必须遵循的规则;事实上,任何实现都可以自由地采用不同的行为方式,而不违反规范。不要编写无效的 HTML,只是为了利用可能看似预期或一致的行为,因为您无法保证这些行为会保持不变。如果决定应该如何处理违反此规则的文档,CSS 实现可以自由地以不同方式匹配共享同一 ID 的元素,甚至停止匹配它们。
换句话说:仅仅因为你能做到,不意味着你应该这么做。

0

这适用于简单的HTML样式,但不适用于查询。

jQuery API文档中:

每个ID值在文档中只能使用一次。如果有多个元素被分配了相同的ID,则使用该ID的查询仅会选择DOM中第一个匹配的元素。然而,不应依赖此行为;具有多个使用相同ID的元素的文档是无效的。


例如,getElementById只会返回具有该ID的第一个元素。 - Rupert Horlick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接