【问题标题】:Can multiple different HTML elements have the same ID if they're different elements?Can multiple different HTML elements have the same ID if they\'re different elements?
【发布时间】:2022-08-08 14:21:51
【问题描述】:

Can multiple HTML elements have the same ID if they're of different element types? Is a scenario like this valid? Eg:

div#foo
span#foo
a#foo

【问题讨论】:

  • While sometimes possible, it's never valid.
  • With all the above being said it is worth to note that it is likely to come across multiple same IDs in a document with user-agent-created content (think frameworks, mv*, react, polymer...). That's if anyone was wondering why a very professional looking XYZ site is full of suchbad practicecoding.
  • The comment from @PaulCreasey is a good way to answer this problematic question. The question title and body do not match; each of them are reasonable yes or no questions but with different correct answers - this could catch out people who aren't paying attention. There's a meta question about how to resolve question mismatches like this, no answers though as of yet: meta.stackoverflow.com/questions/256732
  • Hi @Tidorith! Thanks for commenting. I'm open to suggestion on changing either the title or the body if you have an idea. The original question was asked out of curiosity. Some codegen tool (I think it might've been some Microsoft UI library) was generating elements with identical IDs. I tried reading the spec and testing it out in browsers, but was left confused since browsers seemed to allow it, while the spec said no.
  • @Tidorith Edited the question body a bit. Hope it's better now!

标签: html dom


【解决方案1】:

No.

Element IDs should be unique within the entire document.

【讨论】:

  • What are the consequences of not doing so?
  • @corsiKa the consequence is undefined behavior, for example, what does document.getElementById("#foo") or $("#foo") return when there are multiple #foos? You'll run into problems being able to work with these elements from JS, pass them as selectors to libraries/APIs/Flash, etc.
  • why even use multiple similar id's when you got class for this purpose?
  • Yes, multiple IDs can, in practice, be replaced by using classes. However, classes are intended for applying styles, not identifying elements, making the scope of names much wider and therefore likely to overlap. Especially if using 3rd party libraries. Id as 'identifier' is not intended to be multiplied so there is clearly a need for something in between. The practical use is componentization of sections of a page/dom into separate logical units. Using (at least) 2-layer identification is hence required.
  • Nope. The answer to the question "Is this valid?" does not necessarily have to match the answers to the questions "Do I need this?", "Do I wish this was valid?" or even "Does this dirty hack work in current implementations of the spec?"
【解决方案2】:

I think there is a difference between whether something SHOULD be unique or MUST be unique (i.e. enforced by web browsers).

Should IDs be unique? YES.

Must IDs be unique? NO, at least IE and FireFox allow multiple elements to have the same ID.

【讨论】:

  • So does Chrome (v22 at the time this comment was written). :D
  • According to the spec, this is a MUST, not a SHOULD. (Does it still work in most browsers? Yes. Is it valid HTML? No. Also, for getElementById, the result in such cases is undefined, meaning that there is no way of telling how a browser might chose to handle it.)
  • @leo however this is the real world where browsers don't conform fully to the standards. In this case it could be a good thing, as there is no reason to enforce unique IDs.
  • In HTML5, the spec for getElementById actually does define that thefirstelement with the given ID must be returned (which is how all browsers currently handle the situation anyway) - see my answer below for more.
  • If you don't write HTML according to the specifications then all bets are off. The browser and/or any js library can quite legitimately just break and it's your fault, not theirs
【解决方案3】:

Can multiple elements have the same ID?

Yes - whether they are the same tag or not, browsers will render the page even if multiple elements have the same ID.

Is it Valid HTML?

No. This is still true as of the HTML 5.1 spec. However, the spec also says getElementById must return the first element with the given ID, making the behavior not undefined in the case of an invalid document.

What are the consequences of this type of invalid HTML?

Most (if not all) browsers select the first element with a given ID, when calling getElementById. Some libraries that find elements by ID inherit this behavior, while newer libraries (as gman points out in his answer) will use the more explicit querySelector and querySelectorAll methods, which unambiguously select either thefirstorallmatching elements, respectively. Most (if not all) browsers also apply styles assigned by id-selectors (e.g. #myid) to all elements with the specified ID. If this is what you expect and intend, then there are no unintended consequences. If you expect/intend something else (e.g. for all elements with that ID to be returned by getElementById, or for the style to apply to only one element) then your expectations will not be met and any feature relying on those expectations will fail.

Some javascript librariesdohave expectations that are not met when multiple elements have the same ID (see wootscootinboogie's comment about d3.js)

Conclusion

It's best to stick to the standards, but if you know your code works as expected in your current environments, and these IDs are used in a predictable/maintainable way, then there are only 2 practical reasons not to do this:

  1. To avoid the chance that you are wrong, and one of the libraries you use actuallydoesmalfunction when multiple elements have the same ID.
  2. To maintain forward-compatibility of your website/application with libraries or services (or developers!) you may encounter in the future, that do malfunction when multiple elements have the same ID - which is a reasonable possibility since this is not, technically, valid HTML.

    The power is yours!

【讨论】:

  • The spec you link to doesn't seem to say ids need to be unique in the document, only in that element's tree
  • @gman That's true - but as far as I know a document can only have one node tree at a given time. Of course if you're dealing with multiple documents, or multiple node trees not connected to a document, they can each have a copy of the same ID without being invalid. That seems like an esoteric technicality though. But only slightly more esoteric than the the conditions of validity for this case in general, since most modern libraries have no problem with duplicate IDs ;)
【解决方案4】:

Even if the elements are of different types it can cause you some serious problems...

Suppose you have 3 buttons with the same id:

<button id="myid" data-mydata="this is button 1">button 1</button>
<button id="myid" data-mydata="this is button 2">button 2</button>
<button id="myid" data-mydata="this is button 3">button 3</button>

Now you setup some jQuery code to do something when myid buttons are clicked:

$(document).ready(function ()
{
    $("#myid").click(function ()
    {
        var buttonData = $(this).data("mydata");

        // Call interesting function...
        interestingFunction();

        $('form').trigger('submit');
    });
});

What would you expect? That every button clicked would execute the click event handler setup with jQuery. Unfortunately it won't happen. ONLY the1stbutton calls the click handler. The other 2 when clicked do nothing. It is as if they weren't buttons at all!

So always assign different IDs to HTML elements. This will get you covered against strange things. :)

<button id="button1" class="mybtn" data-mydata="this is button 1">button 1</button>
<button id="button2" class="mybtn" data-mydata="this is button 2">button 2</button>
<button id="button3" class="mybtn" data-mydata="this is button 3">button 3</button>

Now if you want the click event handler to run when any of the buttons get clicked it will work perfectly if you change the selector in the jQuery code to use the CSS class applied to them like this:

$(document).ready(function ()
{
    $(".mybtn").click(function ()
    {
        var buttonData = $(this).data("mydata");

        // Call interesting function...
        interstingFunction();

        $('form').trigger('submit');
    });
});

【讨论】:

  • what if I have a "#content" which I already have referenced in a variable, and a #my-div #content which I only have for a few moments after which I remove the referenced node and forget its variable, after which the #div #content performs a myDiv.outerHTML = myDiv.innerHTML to replace the original. This saves the need to hard copy all styles and contents of #content into #decoy and do the same thing. This makes sense when doing transitions.
  • This means that, even if I use 'append' to add multiple element of same id, DOM only considers first element to be real, ideally 1 ID = 1 Element
【解决方案5】:

No. two elements with the same id are not valid. IDs are unique, if you wish to do something like that, use a class. Don't forget that elements can have multiple classes by using a space as a delimeter:

<div class="myclass sexy"></div>

【讨论】:

    【解决方案6】:

    How about a pragmatic answer.

    Let's go to youtube and run this code

    Object.fromEntries(Object.entries([...document.querySelectorAll('[id]')].reduce((s, e) => { s[e.id] = (s[e.id] || 0) + 1; return s; }, {})).filter(([k,v]) => v > 1))
    

    and see all the repeated ids.

    Changing the code above to show ids repeated more than 10 times here's the list it produced

    additional-metadata-line: 43
    avatar: 46
    avatar-link: 43
    button: 120
    buttons: 45
    byline-container: 45
    channel-name: 44
    container: 51
    content: 49
    details: 43
    dismissable: 46
    dismissed: 46
    dismissed-content: 43
    hover-overlays: 45
    img: 90
    menu: 50
    meta: 44
    metadata: 44
    metadata-line: 43
    mouseover-overlay: 45
    overlays: 45
    repeat: 36
    separator: 43
    text: 49
    text-container: 44
    thumbnail: 46
    tooltip: 80
    top-level-buttons: 45
    video-title: 43
    video-title-link: 43
    

    Other sites that use the same id more than once include Amazon.com, ebay.com, expedia.com, cnn.com

    clearly ids are just another piece of metadata on an element.

    getElementById is pretty much obsolete. You can use querySelectorAll for all elements or querySelector for the first, regardless of selector so if you want all elements with id foo then

    document.querySelectorAll('#foo')  // returns all elements with id="foo"
    

    where as if you want only the first element use querySelector

    document.querySelector('#foo')  // returns the first element with id="foo"
    document.querySelector('.foo')  // returns the first element with class "foo"
    document.querySelector('foo')   // returns the first <foo> element
    document.querySelector('foo .foo #foo') // returns the first element with
                                            // id="foo" that has an ancestor
                                            // with class "foo" who has an
                                            // ancestor <foo> element.
    

    And we can see that using selectors we can find different elements with the same id.

    function addClick(selector, add) {
      document.querySelector(selector).addEventListener('click', function() {
        const e = this.parentElement.querySelector('#value');
        e.textContent = parseInt(e.textContent) + add;
      });
    }
    addClick('.e #foo', 1);
    addClick('.f #foo', 10);
    body { font-size: x-large; font-weight: bold; }
    .a #foo { color: red; }
    .b #foo { color: green; }
    div:nth-child(3) #foo { color: blue; }
    #foo { color: purple }
    <div class="a"><span id="foo">a</span></div>
    <div class="b"><span id="foo">b</span></div>
    <div><span id="foo">c</span></div>
    <span id="foo">d</span>
    <div class="e"><button type="button" id="foo">+1</button>: <span id="value">0</span></div>
    <div class="f"><button type="button" id="foo">+10</button>: <span id="value">0</span></div>

    Where it matters that id is unique

    • &lt;a&gt; tags can reference ids as in &lt;a href="#foo"&gt;. Clicking it will jump the document to the first element with id="foo". Similarly the hash tag in the URL which is effectively the same feature.

    • &lt;label&gt; tags have a for attribute that specifies which element they are labeling by id. Clicking the label clicks/activates/give-the-focus-to the corresponding element. The label will only affect the first element with a matching id

    label { user-select: none; }
    <p>nested for checking</p>
    <form>
      <div><input type="checkbox" id="foo"><label for="foo">foo</label></div>
    </form>
    <form>
      <div><input type="checkbox" id="foo"><label for="foo">foo (clicking here will check first checkbox)</label></div>
    </form>

    Otherwise, id is just another tool in your toolbox.

    【讨论】:

    • Interesting answer, thanks! I've observed generated duplicated IDs in some third party code (I forgot what it was now), and while I knew it would work in most browsers, I was curious if there are any serious implications/downsides to this, and whether it was actually valid since at the time I've believed it wasn't valid (and it's still not valid, but it turns out most clients are lenient).
    • I would argue the spec is invalid. Given some of the largest sites on the planet are using the feature the spec should change to reflect what browsers are actually doing.
    【解决方案7】:

    The official spec for HTML states that id tags must be uniqueANDthe official spec also states that if the render can be completed, it must (i.e. there are no such thing as "errors" in HTML, only "invalid" HTML).So, the following is how id tags actually work in practice. They are allinvalid, but still work:

    This:

    <div id="unique">One</div>
    <div id="unique">Two</div>
    

    Renders fine in all browsers. However, document.getElementById only returns an object, not an array; you will only ever be able to select the first div via an id tag. If you were to change the id of the first div using JavaScript, the second ID would then be accessible with document.getElementById (tested on Chrome, FireFox & IE11). You can still select the div using other selection methods, and it's id property will be returned correctly.

    Please notethis above issue opens a potential security vulnerability in sites that render SVG images, as SVGs are allowed to contain DOM elements, and also id tags on them (allows script DOM redirects via uploaded images). As long as the SVG is positioned in the DOM before the element it replaces, the image will receive all JavaScript events meant for the other element.

    This issue is currently not on anyone's radar as far as I know, yet it's real.

    This:

    <div id="unique" id="unique-also">One</div>
    

    Also renders fine in all browsers. However, only thefirstid you define this way is utilized, if you tried document.getElementById('unique-also'); in the above example, you would be returnednull(tested on Chrome, FireFox & IE11).

    This:

    <div id="unique unique-two">Two</div>
    

    Also renders fine in all browsers, however, unlike class tags that can be separated by a space, the id tag allows spaces, so the id of the above element is actually "unique unique-two", and asking the dom for "unique" or "unique-two" in isolation returnsnullunless otherwise defined elsewhere in the DOM (tested on Chrome, FireFox & IE11).

    【讨论】:

    • "the id tag allows spaces" - Although, according to the spec, the "The value must not contain any space characters."
    • I agree. However, there is the spec, and there is how the browsers operate. Browsers historically treat the spec as something of a goal, but have not been strict on many of the items. I think they do this because if they met the spec it would break lots of existing sites or something. I mention at top that although these things work, they are invalid.
    【解决方案8】:

    SLaks answer is correct, but as an addendum note that the x/html specs specify that all ids must be uniquewithin a (single) html document. Although it's not exactly what the op asked, there could be valid instances where the same id is attached to different entities across multiple pages.

    Example:

    (served to modern browsers) article#main-content {styled one way}
    (served to legacy) div#main-content {styled another way}

    Probably an antipattern though. Just leaving here as a devil's advocate point.

    【讨论】:

    • Good point. Although the dynamically generated content that is supposed to be inserted into another page should avoid ids altogether. Ids are like globals in programming languages, you can use them, and there are valid cases where it's a nice hack that simplifies things. It's a nice practice to consider doing things right before doing hacks.
    【解决方案9】:

    And for what it's worth, on Chrome 26.0.1410.65, Firefox 19.0.2, and Safari 6.0.3 at least, if you have multiple elements with the same ID, jquery selectors (at least) will return the first element with that ID.

    e.g.

    <div id="one">first text for one</div>
    <div id="one">second text for one</div>
    

    and

    alert($('#one').size());
    

    See http://jsfiddle.net/RuysX/ for a test.

    【讨论】:

    • Unless you use a more complex selector, such as div#one That of course doesn't change the fact that it's invalid.
    • Possibly this answer is true, I am saying this from experience.
    【解决方案10】:

    Well, using the HTML validator at w3.org, specific to HTML5, IDs must be unique

    Consider the following...

    <!DOCTYPE html> 
    <html>
        <head>
            <meta charset="UTF-8">
            <title>MyTitle</title> 
        </head>
        <body>
            <div id="x">Barry</div>
            <div id="x">was</div>
            <div id="x">here</div>
        </body>
    </html>
    

    the validator responds with ...

    Line 9, Column 14: Duplicate ID x.      <div id="x">was</div>
    Warning Line 8, Column 14: The first occurrence of ID x was here.       <div id="x">Barry</div>
    Error Line 10, Column 14: Duplicate ID x.       <div id="x">here</div>
    Warning Line 8, Column 14: The first occurrence of ID x was here.       <div id="x">Barry</div>
    

    ... but the OP specifically stated - what about different element types. So consider the following HTML...

    <!DOCTYPE html> 
    <html>
        <head>
            <meta charset="UTF-8">
            <title>MyTitle</title> 
        </head>
        <body>
            <div id="x">barry
                <span id="x">was here</span>
            </div>
        </body>
    </html>
    

    ... the result from the validator is...

    Line 9, Column 16: Duplicate ID x.          <span id="x">was here</span>
    Warning Line 8, Column 14: The first occurrence of ID x was here.       <div id="x">barry
    

    Conclusion:

    In either case (same element type, or different element type), if the id is used more than once it is not considered valid HTML5.

    【讨论】:

      【解决方案11】:

      Yes they can.

      I don't know if all these anwers are outdated, but just open youtube and inspect the html. Try to inspect the suggested videos, you'll see that they all have the same Id and repeating structure as follows:

      <span id="video-title" class="style-scope ytd-compact-radio-renderer" title="Mix - LARA TACTICAL">
      

      【讨论】:

        【解决方案12】:

        <div id="one">first text for one</div>
        <div id="one">second text for one</div>
        
        var ids = document.getElementById('one');

        ids contain only first div element. So even if there are multiple elements with the same id, the document object will return only first match.

        【讨论】:

          【解决方案13】:

          It's possible to have duplicate ids. I have tried adding the todoitem from javascript and it added to the dom successfully. This is the html code and javscript code.

          【讨论】:

            【解决方案14】:

            Nope, IDs have to be unique. You can use classes for that purpose

            <div class="a" /><div class="a b" /><span class="a" />
            
            div.a {font: ...;}
            /* or just: */
            .a {prop: value;}
            

            【讨论】:

              【解决方案15】:

              Is it possible to have more than one student in a class having same Roll/Id no? In HTMLid attribute is like so. You may use same class for them. e.g:

              <div class="a b c"></div>
              <div class="a b c d"></div>
              

              And so on.

              【讨论】:

                【解决方案16】:

                We can use class name instead of using id. html id are should be unique but classes are not. when retrieving data using class name can reduce number of code lines in your js files.

                $(document).ready(function ()
                {
                    $(".class_name").click(function ()
                    {
                        //code
                    });
                });

                【讨论】:

                  【解决方案17】:

                  I think you can't do it because Id is unique you have to use it for one element . You can use class for the purpose

                  【讨论】:

                    猜你喜欢
                    • 2022-12-26
                    • 2022-12-27
                    • 2022-12-02
                    • 2016-08-17
                    • 2022-12-27
                    • 1970-01-01
                    • 2022-12-01
                    • 2015-09-21
                    • 2022-12-01
                    相关资源
                    最近更新 更多