140

Just browsing the google maps source code. In their header, they have 2 divs with id="search" one contains the other, and also has jstrack="1" attribute. There is a form separating them like so:

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

Since this is google, I'm assuming it's not a mistake.

So how bad can it really be to violate this rule? As long as you are careful in your css and dom selection, why not reuse id's like classes? Does anyone do this on purpose, and if so, why?

9
  • 112
    "Since this is google, I'm assuming it's not a mistake." --> Google are not infallible. They make mistakes like the rest of us. Dec 27, 2011 at 17:28
  • 45
    actually the guys at google have SEARCH bolted in their minds so they can't think of any other id's :P Dec 27, 2011 at 17:53
  • 13
    I have a feeling that that page is rendered from different html fragments so one developer in one fragment used that id, and the same happened with other developer in the other fragment.
    – Luciano
    Dec 27, 2011 at 18:20
  • 13
    The whole question of "how bad is it really" just reminds me of this: xkcd.com/292 Dec 28, 2011 at 17:47
  • 4
    @DanielRoseman xkcd does it as well: what-if.xkcd.com/23/#question
    – SQB
    Jul 17, 2014 at 5:55

5 Answers 5

153

Specification says UNIQUE

HTML 4.01 specification says ID must be document-wide unique.

HTML 5 specification says the same thing but in other words. It says that ID attributes must be unique amongst all the IDs in the element's tree, which is basically the document if we read the definition of it.

Avoid duplication

But since HTML renderers are very forgiving when it comes to HTML rendering they tolerate duplicate IDs. This should be avoided if at all possible and strictly avoided when programmatically accessing elements by IDs in JavaScript. I'm not sure what getElementById function should return when several matching elements are found? Should it:

  • return an error?
  • return first matching element?
  • return last matching element?
  • return a set of matching elements?
  • return nothing?

But even if browsers work reliably these days, nobody can guarantee this behavior in the future since this is against specification. That's why I recommend you never duplicate IDs within the same document.

13
  • 1
    @missingno: I added a link to HTML 5 specification that talks about the same thing but in different wording. Dec 27, 2011 at 20:26
  • 9
    According to the DOM spec, "If more than one element has an ID attribute with that value, what is returned is undefined" (by which it means that there is no defined "correct" result, rather than the actual value undefined). It's rarely a good idea to rely on undefined behaviour. Dec 28, 2011 at 0:22
  • 2
    Worth noting with HTML5, the data- attribute comes in handy for when one might be tempted to assign multiple things the same ID. This lets you have many different ID's with one common data-something attribute in common. Still, all browsers that I know of ignore unknown attributes, so they're probably safe in just about every modern-ish browser lacking full HTML support.
    – Tim Post
    Mar 3, 2012 at 15:53
  • 3
    @JoachimSauer: When you use data attributes you can have key-value pairs which is not true when you use CSS classes. In that case they're all like boolean properties. An element either has a CSS class or not. If you'd want values with CSS classes then you'd have to somehow combine them into CSS class name and parse that afterwards. I hope you can now see benefits of using data attributes. And they're also supported directly out of the box by jQuery when you simply refer to data-something="123" attribute with $(elem).data("something"). Sep 4, 2012 at 10:39
  • 1
    @RobertKoritnik: Of course! I didn't think of that use-case. I only thought about the case of id="search". Sep 4, 2012 at 10:46
33

You asked "how bad". So to flesh out @RobertKoritnik's (entirely accurate) answer a bit...

That code is incorrect. Incorrect doesn't come in shades of grey. This code violates the standard and is therefore incorrect. It would fail validation checking, and it should.

That said, no browser currently on the market would complain about it, or have any problem with it at all. Browsers would be within their rights to complain about it, but none of the current versions of any of them currently do. Which doesn't mean future versions might not treat this code badly.

Your behavior trying to use that ID as a selector, either in css or javascript, is unguessable and probably varies from browser to browser. I suppose a study could be done to see how each browser reacts to that. I think in the best case, it would treat it just like "class=", and select the list of them. (That might confuse JavaScript libraries, though--if I were the author of jQuery, I might have optimized my selector code so that if you come to me with a selector starting with "#", I expect a single object, and getting a list might bork me completely.)

It also might select the first one, or possibly the last one, or select none of them, or crash the browser entirely. No way to tell without trying it.

"How bad" then depends entirely on how strictly a particular browser implements the HTML spec, and what it does when confronted with a violation of that spec.

EDIT: I JUST happened to come across this today. I'm pulling in various components from search forms on various types of entities to produce a great big all-in-one reporting utility for this site, I'm loading up the remote pages' search forms in hidden divs and slotting them into my report generator when the appropriate entity type is selected as the source for the report. So there's a hidden version of the form, and a version displayed in the report generator. The JavaScript that came with, in all cases, refers to elements by ID, of which there are now TWO on the page--the hidden one, and the displayed one.

What jQuery seems to be doing is selecting me the FIRST one, which in all cases is exactly the one I DON'T want.

I'm working around this by writing selectors to specify the region of the page I want to get my field in (ie: $('#containerDiv #specificElement') ). But there's one answer to your question--jQuery on Chrome definitely behaves a particular way when confronted with this spec violation.

3
  • ... a related question: stackoverflow.com/q/29295824/287948 about obligation of IDs in a CSS fast profile. Mar 27, 2015 at 14:22
  • 6
    "Incorrect doesn't come in shades of grey." I see this a lot and it's one of those things that's technically correct but not "true" in life or in programming. You indirectly cover that pretty thoroughly in your answer and I could expound but this scene from The Big Bang Theory does such a good job that I'll let it speak for me and hopefully make someone laugh... Stuart vs Sheldon youtube.com/watch?v=F_1zoX5Ax9U
    – Night Owl
    Mar 1, 2016 at 21:42
  • this is an 8 year old answer, but I think it's very unbalanced how you hyperbole on OP's question yet don't complain much about browsers' permissive and dangerous behaviour about repeated ids, which is way worse than what OP's trying to do. Oct 8, 2019 at 15:41
22

How bad is it really?

  1. It makes me cry
  2. It's invalid
  3. Many javascript libraries will not work as expected
  4. It makes your code confusing

Experience says that getElementById in major browsers will return the first matched element in the document. But this may not always be the case in the future.

When jQuery is given an id eg #foo, it uses getElementById and mimics that behaviour. If you have to work around this (that's sad), you can use $("*#foo") which will convince jQuery to use getElementsByTagName and return a list of all matched elements.

I often have to write code for other sites, and I have to work around this. In a just world, I would not have to redesign functions to start off by checking if an ID is unique. IDs should always be unique. The world is cruel and that's why I cry.

1
  • 5
    This answer made me cry... of laughter!
    – A1rPun
    Jun 30, 2015 at 10:23
8

You can do a great many things - but that doesn't mean that you should.

As a programmer (generally speaking) we build our lives on being precise and following the rules - here is a rule that is simple to follow, that is fairly fundamental to what we do - we like (depend upon) unique identifiers within a given scope...

Breaking the rule is something we can do because the browser are way too accommodating - but really we'd all be better off if browsers were strict about needing well formed and valid HTML, the small amount of pain it would have caused would have long since been repaid!

So, is it really that bad? As a programmer how can you even ask? Its a crime against civilisation (-:


Addendum:

You write that browsers are too accommodating like it's bad thing

I do, because it is - we're not talking about complicated rules, we're talking substantially about making things well formed and otherwise applying rules which can be tested mechanically and which in turn make it easier for the result to be processed mechanically. If the browsers had been strict then the tools would very rapidly have adapted to support that - it wasn't so they didn't, some to the extent they exploit that failing instead. Just think on this - email would have been a much nicer medium if MS and Netscape had not screwed it up by allowing unrestricted HTML when a far less complex "email markup language" with explicit support for quoted text would have given us a far better tool... but that ship sailed and similarly we can't close the stable door on what browsers allow (we should, HTML5 should have) but we can't

6
  • You write that browsers are too accommodating like it's bad thing, but surely you don't believe that? Dec 27, 2011 at 22:42
  • 4
    I can't speak for Murph, but I for sure think it is a really bad thing. Then again, without this level of forgiveness, the web may not have had the impulse to grow like we know it.
    – Andrea
    Dec 27, 2011 at 23:37
  • 1
    @Andrea: The internet would not have grown as we know it. It would have grown more slowly. But it would also have had a more solid basis of what is and is not correct code. Fast-but-sloppy may work, but I much prefer slower-but-correct. Especially since it's not like we'd only be talking about a couple of years of growth or so. Dec 28, 2011 at 5:40
  • 3
    @Andrea I'd bet that it would have grown almost as quickly - the tools would simply have evolved to deal with the problem. Whereas in many cases the tools were the root cause of poor markup. The fact is that people tend to do the least necessary - the step to "well formed" is a relatively small one and easy enough to test for and enforce and people would have accommodated that without significant stress
    – Murph
    Dec 28, 2011 at 11:36
  • 2
    It's not horrible that browsers are accommodating. It IS horrible that they're all accommodating in different ways.
    – Dan Ray
    Dec 29, 2011 at 18:45
8

In Scripting: getElementByID will return only the first match. In CSS: #id will affect ALL elements with that ID. In Browser Render won't be of any effect.

This is the behavior of w3c standard. Not a possible one, it's the facto defined one.

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

5
  • 7
    This is one possible behaviour. getElementById could perfectly return any element, or even a null object. CSS effect could be on any elements, or none or all of them. Or the browser could crash. Out of the standard, the behaviour is undefined
    – rds
    Dec 27, 2011 at 22:35
  • 2
    It's not out of the standard because the standard specify what to do in those situations. So no, getElementById could not return any element, the standard says explicit that i will return the first match. I agree that behaviour out of the standard is undefined, what you don't understand is that all those cases are part of the standard. Apr 3, 2014 at 21:27
  • 1
    This answer would be somewhat better if it actually included, as a reference, a quote of the relevant part of the standard (or at least a section number).
    – yoniLavi
    Oct 28, 2015 at 20:30
  • 2
    @yoniLavi updated. Oct 28, 2015 at 20:35
  • 2
    Thanks @Bart . You're absolutely right :) The standard says "Returns the first element within node’s descendants whose ID is elementId."
    – yoniLavi
    Oct 28, 2015 at 23:32

Not the answer you're looking for? Browse other questions tagged or ask your own question.