Two HTML elements with same id attribute: How bad is it really?
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?
"Since this is google, I'm assuming it's not a mistake." --> Google are not infallible. They make mistakes like the rest of us.
actually the guys at google have *SEARCH* bolted in their minds so they can't think of any other id's :P
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.
The whole question of "how bad is it really" just reminds me of this: http://xkcd.com/292/
Given that it's google it may well also be a hack performed with full knowledge of how it operates in all browsers. That doesn't mean you should emulate it; future specs and browsers may treat it differently, and it's technically a validation error. .
It's not HTML, but duplicate ids that where not detected correctly are one of the vulnerabilities in the recent SAML-related mass-vulnerabilities of SSO systems.. So consider that an answer to "how bad *could* it be."
Specification says UNIQUE
HTML 4.01 specification says ID must be document-wide unique.
getElementByIdfunction 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.
What about HTML5? There is a big difference between what is written in the HTML4 spec and what is accepted by browsers, etc.
@missingno: I added a link to HTML 5 specification that talks about the same thing but in different wording.
So CSS allows us to define a selector like div#foo. Since there should only be one #foo in the document, what is the purpose of this? For re-using the same stylesheet across multiple documents?
@ThomasDignan Yes. It also tells other developers that, if they're doing refactoring, this css block is meant for this type of html element - not all css attributes will be valid if what the ID is on changes.
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.
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.
@TimPost: but then again, why not simply use `class`? It's all about classification and who says that only CSS gets to play with `class`?
@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")`.
@RobertKoritnik: Of course! I didn't think of that use-case. I only thought about the case of `id="search"`.
Question: Would having non-unique IDs in your HTML break the page if it was an XHTML document instead of HTML? (I'm not sure if it does in this case.) Generally, my rule of thumb is, if it'd break XHTML, don't do it.
I don't think it would because it would still be valid XML. And to my knowledge there's no XSD that could define values across several non-related elements. So if it can't be defined in XSD, it won't break XHTML. But that's just my thinking...
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.
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.
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.
... a related question: http://stackoverflow.com/q/29295824/287948 about obligation of IDs in a CSS fast profile.
"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 https://www.youtube.com/watch?v=F_1zoX5Ax9U
How bad is it really?
- It makes me cry
- It's invalid
- 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.
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 (-:
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
You write that browsers are too accommodating like it's bad thing, but surely you don't believe that?
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: 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.
@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
It's not horrible that browsers are accommodating. It IS horrible that they're all accommodating *in different ways*.
getElementByIDwill return only the first match. In CSS:
#idwill 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.
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_
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.
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).