Can multiple different HTML elements have the same ID if they're different elements?

后端 未结 16 1885
无人及你
无人及你 2020-11-21 05:30

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
相关标签:
16条回答
  • 2020-11-21 06:08

    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.

    0 讨论(0)
  • 2020-11-21 06:08

    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 have selected and still do select the first element with a given ID, when calling getElementById. Most libraries that find elements by ID inherit this behavior. 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, 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 libraries do have 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 actually does malfunction 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!

    0 讨论(0)
  • 2020-11-21 06:09

    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 the 1st button 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');
        });
    });
    
    0 讨论(0)
  • 2020-11-21 06:09

    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('span');
        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>0</span></div>
    <div class="f"><button type="button" id="foo">+10</button>: <span>0</span></div>

    Where it matters that id is unique

    • <a> tags can reference ids as in <a href="#foo">. 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.

    • <label> 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.

    0 讨论(0)
提交回复
热议问题