具有相同id属性的两个HTML元素:到底有多糟?


122

只需浏览google maps源代码。在标题中,他们有2个div,其中id =“ search”一个包含另一个,并且还具有jstrack =“ 1”属性。有一种形式将它们分开,如下所示:

<div id="search" jstrack="1">
    <form action="/maps" id="...rest isn't important">
        ...
        <div id="search">...

由于这是google,我假设这不是一个错误。

那么违反此规则真的有多严重?只要您谨慎选择CSS和dom,为什么不重用id一样的类?有人故意这样做吗?如果是,为什么?


102
“由于这是谷歌,所以我认为这不是一个错误。” -> Google并非万无一失。他们像我们其他人一样犯错误。
Joeri Sebrechts

43
实际上,谷歌的家伙脑子里塞满了搜索功能,因此他们无法想到其他任何ID:P
Pankaj Upadhyay

10
我感觉该页面是由不同的html片段呈现的,因此一个片段中的一个开发人员使用了该id,而另一个片段中的其他开发人员也发生了同样的情况。
卢西亚诺

10
整个问题“它到底有多糟”真让我想起了这个问题:xkcd.com/292
Daniel Roseman

3
@DanielRoseman xkcd也能做到:what-if.xkcd.com/23/#question
SQB

Answers:


140

规格说唯一

HTML 4.01规范说ID必须在文档范围内是唯一的。

HTML 5规范说了同样的话,换句话说。它说ID在它的home子树中必须是唯一的,如果我们阅读 ID 的定义,它基本上就是文档。

避免重复

但是,由于HTML渲染器在处理HTML渲染时非常宽容,因此它们允许重复的ID。应尽可能避免这种情况,在使用JavaScript中的ID以编程方式访问元素时应严格避免。我不确定getElementById找到多个匹配元素时应返回哪个函数?应该是:

  • 返回错误?
  • 返回第一个匹配元素?
  • 返回最后一个匹配的元素?
  • 返回一组匹配的元素?
  • 什么都不返回?

但是,即使这些天浏览器能够可靠地运行,也没有人能够保证这种行为,因为这违反了规范。因此,我建议您不要在同一文档中重复ID


1
@missingno:我添加了指向HTML 5规范的链接,该链接讨论的是同一件事,但措辞不同。
罗伯特·科里特尼克

6
根据DOM规范,“如果多个元素具有具有该值的ID属性,则返回的内容是不确定的”(这意味着没有定义的“正确”结果,而不是实际值undefined)。依靠不确定的行为很少是一个好主意。
lonesomeday '12

1
值得一提的是HTML5,该data-属性在可能试图为多个事物分配相同ID时非常有用。这使您可以拥有许多具有相同公共data-something属性的不同ID 。尽管如此,我所知道的所有浏览器都会忽略未知属性,因此对于几乎所有缺乏完整HTML支持的现代浏览器来说,它们可能都是安全的。
Tim Post

2
@JoachimSauer:使用数据属性时,可以具有键-值对,而使用CSS类时,键-值对不正确。在那种情况下,它们都像布尔属性。一个元素是否具有CSS类。如果您想要CSS类的值,则必须以某种方式将它们组合为CSS类名,然后进行解析。我希望您现在可以看到使用data属性的好处。当您仅使用引用data-something="123"attribute 时,jQuery也直接支持它们$(elem).data("something")
罗伯特·科里特尼克

1
@RobertKoritnik:当然可以!我没想到那个用例。我只想到了的情况id="search"
Joachim Sauer 2012年

30

您问“有多糟”。所以充实@RobertKoritnik(完全正确)的答案...

该代码不正确。错误不会以灰色阴影出现。该代码违反标准,因此不正确。这将使验证检查失败,应该这样做。

就是说,目前市场上没有浏览器会抱怨它,或者对此有任何问题。浏览器有权投诉该浏览器,但是任何浏览器的当前版本都没有。这并不意味着将来的版本可能不会对此代码造成不良影响。

您尝试使用该ID作为CSS或javascript中的选择器的行为是无法猜测的,并且可能因浏览器而异。我想可以做一个研究,看看每个浏览器对此有何反应。我认为在最好的情况下,它将像“ class =”一样对待它,并选择它们的列表。(不过,这可能会混淆JavaScript库-如果我是jQuery的作者,我可能已经优化了选择器代码,因此,如果您使用以“#”开头的选择器来找我,那么我希望得到一个对象,并得到一个清单可能会让我完全失望。)

它还可能选择第一个,或者可能选择最后一个,或者都不选择,或者完全使浏览器崩溃。没有尝试就无法告诉。

那么,“有多糟糕”完全取决于特定浏览器严格执行HTML规范的方式,以及在遇到违反该规范时的行为。

编辑:我只是碰巧今天遇到了这个。我从各种类型的实体上的搜索表单中提取各种组件,以为该站点生成一个很大的大型多合一报告实用程序,我将远程页面的搜索表单加载到隐藏的div中,并将其放入我的选择适当的实体类型作为报告源时的报告生成器。因此,该表单有一个隐藏版本,并且在报告生成器中显示了一个版本。在所有情况下,随附的JavaScript均按ID指代元素,页面上现在有两个元素-隐藏的元素和显示的元素。

jQuery似乎在做的是选择我第一个,在所有情况下,这都是我不想要的。

我正在通过编写选择器来指定要在其中获取字段的页面区域(即:$('#containerDiv #specificElement'))来解决此问题。但是您的问题有一个答案-Chrome上的jQuery在遇到这种规范违规时肯定表现出特定的方式。


...一个相关的问题:关于CSS快速配置文件中ID义务的stackoverflow.com/q/29295824/287948
彼得·克劳斯

3
“不正确的不是灰色阴影。” 我经常看到这一点,这是技术上正确的事情之一,但在生活或编程中不是“正确的”事情。您可以在回答中完全间接地涵盖这一点,我可以阐述一下,但是《大爆炸理论》中的这一幕做得很好,我会让它为我说话,并希望使某人发笑... Stuart vs Sheldon youtube.com/看吗?v = F_1zoX5Ax9U
夜猫子

这是一个有8年历史的答案,但我认为您在OP问题上夸张的做法非常不平衡,但又不要抱怨浏览器对重复ID的宽容和危险行为,这比OP试图做的要糟糕得多。
erandros

20

真的有多糟?

  1. 这让我哭
  2. 无效的
  3. 许多JavaScript库无法按预期运行
  4. 它使您的代码混乱

经验表明,主流浏览器中的getElementById将返回文档中的第一个匹配元素。但是,将来可能并非总是如此。

当给jQuery一个ID(例如#foo)时,它将使用getElementById并模仿该行为。如果必须解决此问题(很可惜),则可以使用$(“ * #foo”),这将使jQuery确信使用getElementsByTagName并返回所有匹配元素的列表。

我经常不得不为其他站点编写代码,并且必须解决此问题。在一个公正的世界中,我不必通过检查ID是否唯一来重新设计功能。ID应该始终是唯一的。世界是残酷的,这就是我哭泣的原因。


5
这个答案让我哭了……笑声!
A1rPun 2015年

8

可以做很多事情-但这并不意味着您应该做。

作为一名程序员(通常来说),我们的生活是建立在精确且遵循规则的基础上的-这是一条易于遵循的规则,对我们所做的工作而言是非常基础的-我们喜欢(取决于)给定范围内的唯一标识符...

违反规则是我们可以做的事情,因为浏览器太适应了-但是,如果浏览器严格要求格式正确和有效的HTML,我们真的会更好,因为它会给您带来一点点痛苦已还清!

那么,真的那么糟糕吗?作为程序员,您怎么能问?它是危害文明的罪行(-:


附录:

您写道,浏览器过于宽松,这是一件坏事

我这样做是因为,这是-我们不是在谈论复杂的规则,而是在谈论使事物形成良好的结构,或者应用可以机械测试的规则,从而可以更轻松地对结果进行机械处理。如果浏览器很严格,那么这些工具将很快适应这种情况-并非如此,他们没有这样做,某种程度上是他们利用了失败的原因。试想一下-如果MS和Netscape没有通过允许无限制的HTML来搞砸它,那么电子邮件本来是一种更好的媒介,而当一种复杂得多的“电子邮件标记语言”具有对引用文本的显式支持时,电子邮件将为我们提供一个更好的工具...但是那艘船航行了,我们同样可以应该有),但我们不能


您写的是,浏览器适应性很强,这是一件坏事,但是您肯定不相信吗?
KaptajnKold

4
我不能代表墨菲(Murph),但我可以肯定的认为这是一件很糟糕的事情。再有,如果没有这种宽恕,网络可能不会像我们所知道的那样具有增长的冲动。
Andrea

1
@Andrea:互联网不会像我们所知道的那样增长。它会增长得更慢。但这也将为什么是正确的代码提供更坚实的基础。快速但草率的工作可能会起作用,但我更喜欢速度较慢但正确的方法。尤其是因为这并不是说我们只谈论几年的增长。
Nicol Bolas

3
@Andrea我敢打赌它会以几乎一样快的速度增长-这些工具将可以解决问题。在许多情况下,工具是不良标记的根本原因。事实是,人们倾向于做最少的事情-“结构良好”的步骤相对较小,足够容易测试和执行,人们本来可以在没有很大压力的情况下解决这一问题
-Murph,

1
浏览器可以容纳并不可怕。他们都以不同的方式容纳住是可怕的。
丹·雷

7

在Scripting中:getElementByID将仅返回第一个匹配项。在CSS中:#id将影响具有该ID的所有元素。在浏览器中,渲染不会有任何效果。

这是w3c标准的行为。这是不可能的,这是事实定义的。

https://dom.spec.whatwg.org/#interface-nonelementparentnode


7
这是一种可能的行为。getElementById可以完美地返回任何元素,甚至返回null对象。CSS效果可以作用于任何元素,或者不作用于所有元素。否则浏览器可能会崩溃。超出标准,行为未定义
rds

2
这不是超出标准的范围,因为标准指定了在这些情况下的操作。所以不,getElementById无法返回任何元素,标准明确要求我将返回第一个匹配项。我同意未定义标准的行为,您不了解的是所有这些情况都是标准的一部分。
Bart Calixto 2014年

1
如果该答案实际上包括标准的相关部分(或至少是部分编号)的引用作为参考,则可能会更好。
yoniLavi 2015年

2
@yoniLavi更新。
Bart Calixto 2015年

2
谢谢@Bart。您是完全正确的:)标准说:“返回ID为elementId的节点后代中的第一个元素。”
yoniLavi 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.