Могут ли несколько разных HTML-элементов иметь одинаковый идентификатор, если они разные?


144

Могут ли несколько элементов HTML иметь одинаковый идентификатор, если они относятся к разным типам элементов? Верен ли такой сценарий? Например:

div#foo
span#foo
a#foo

26
Иногда это возможно, но никогда не действует.
— Пол Кризи

3
При всем вышесказанном стоит отметить, что в документе с контентом, созданным пользовательским агентом (например, frameworks, mv *, react, полимер ...), вероятно, встретятся несколько одинаковых идентификаторов. Вот если кому-то было интересно, почему очень профессионально выглядящий сайт XYZ полон такой плохой практики кодирования.
— Лукаш Матысяк

Комментарий от @PaulCreasey - хороший способ ответить на этот проблемный вопрос. Заголовок и текст вопроса не совпадают; каждый из них является разумным вопросом «да» или «нет», но с разными правильными ответами - это может уловить людей, которые не обращают внимания. Есть мета-вопрос о том, как разрешить подобные несоответствия вопросов, но пока ответов нет: meta.stackoverflow.com/questions/256732
— Tidorith

Привет, @Tidorith! Спасибо за комментарий. Я открыт для предложения об изменении заголовка или текста, если у вас есть идея. Первоначальный вопрос был задан из любопытства. Какой-то инструмент кодогенерации (я думаю, это могла быть какая-то библиотека пользовательского интерфейса Microsoft) генерировал элементы с идентичными идентификаторами. Я попытался прочитать спецификацию и протестировать ее в браузерах, но остался в замешательстве, поскольку браузеры, казалось, позволяли это, а в спецификации говорилось «нет».
— omninonsense

@Tidorith Немного отредактировал текст вопроса. Надеюсь, теперь стало лучше!
— omninonsense

Ответы:


181

Нет.

Идентификаторы элементов должны быть уникальными в пределах всего документа.


89
Каковы последствия невыполнения этого требования?
— corsiKa

17
@corsiKa последствием является неопределенное поведение, например, что возвращает document.getElementById ("# foo") или $ ("# foo") при наличии нескольких #foos? Вы столкнетесь с проблемами, когда сможете работать с этими элементами из JS, передавать их в качестве селекторов в библиотеки / API / Flash и т. Д.
— mrooney

81
Это неверно. Вполне возможно иметь несколько элементов с одним и тем же идентификатором. Обычно это не лучшая практика , но время от времени она используется. Кажется, все цитируют, как будут работать селекторы, ну, если вы знаете, что у вас будут конфликтующие идентификаторы, вы используете свои селекторы с родителем, где идентификаторы под родительским элементом будут уникальными. например, $('div#car span#size)и $('div#truck span#size').
— BJury 02

19
зачем даже использовать несколько одинаковых идентификаторов, когда у вас есть класс для этой цели?
— Макс Яри

8
Да, на практике несколько идентификаторов можно заменить с помощью классов. Однако классы предназначены для применения стилей, а не для идентификации элементов, что значительно увеличивает объем имен и, следовательно, может перекрываться. Особенно при использовании сторонних библиотек. Id как «идентификатор» не предназначен для умножения, поэтому явно необходимо что-то среднее. Практическое использование - это разбиение разделов страницы / домена на отдельные логические блоки. Следовательно, требуется использование (как минимум) двухуровневой идентификации.
— Ален Сильджак

88

Я думаю, есть разница между тем, ДОЛЖНО ли что-то быть уникальным или ДОЛЖНО быть уникальным (т. Е. Обеспечивается веб-браузерами).

Должны ли идентификаторы быть уникальными? ДА.

Идентификаторы должны быть уникальными? НЕТ, по крайней мере IE и FireFox позволяют нескольким элементам иметь один и тот же идентификатор.


6
Как и Chrome (версия 22 на момент написания этого комментария). : D
— omninonsense

27
Согласно спецификации , это ОБЯЗАТЕЛЬНО, а не ОБЯЗАТЕЛЬНО. (Он по-прежнему работает в большинстве браузеров? Да. Это правильный HTML? Нет. Кроме того, getElementByIdв таких случаях результатом является то undefined, что невозможно определить, как браузер может решить его обрабатывать.)
— Лео

2
@leo, однако, это реальный мир, где браузеры не полностью соответствуют стандартам. В этом случае это может быть хорошо, поскольку нет причин вводить уникальные идентификаторы.
— BJury 02

3
В HTML5 спецификация на getElementByIdсамом деле определяет, что должен быть возвращен первый элемент с данным идентификатором (именно так все браузеры в настоящее время обрабатывают ситуацию) - подробнее см. Мой ответ ниже.
— млцы

1
Не плачь, пользуйся jQuery. @leo
— Максима Алекз 06

72

Могут ли несколько элементов иметь одинаковый идентификатор?

Да - независимо от того, являются ли они одним и тем же тегом, браузеры будут отображать страницу, даже если несколько элементов имеют одинаковый идентификатор.

Это действительный HTML?

Нет. Это все еще верно для спецификации HTML 5.1 . Однако в спецификации также говорится, что getElementById должен возвращать первый элемент с данным идентификатором , что делает поведение не неопределенным в случае недопустимого документа.

Каковы последствия этого типа недействительного HTML?

Большинство (если не все) браузеры выбрали и все еще выбирают первый элемент с заданным идентификатором при вызове getElementById. Большинство библиотек, которые находят элементы по идентификатору, наследуют это поведение. Большинство (если не все) браузеры также применяют стили, назначенные селекторами идентификаторов (например #myid), ко всем элементам с указанным идентификатором. Если это то, чего вы ожидаете и намерены, то непредвиденных последствий не будет. Если вы ожидаете / намереваетесь что-то еще (например, чтобы все элементы с этим идентификатором были возвращены, или чтобы стиль применялся только к одному элементу), ваши ожидания не будут выполнены, и любая функция, основанная на этих ожиданиях, потерпит неудачу.

Некоторые библиотеки javascript действительно имеют ожидания, которые не оправдываются, когда несколько элементов имеют одинаковый идентификатор (см . Комментарий wootscootinboogie о d3.js)

Вывод

Лучше придерживаться стандартов, но если вы знаете, что ваш код работает должным образом в ваших текущих средах, и эти идентификаторы используются предсказуемым / поддерживаемым способом, то есть только две практические причины не делать этого:

  1. Чтобы избежать вероятности того, что вы ошибаетесь, и одна из используемых вами библиотек действительно не работает, когда несколько элементов имеют одинаковый идентификатор.
  2. Чтобы поддерживать прямую совместимость вашего веб-сайта / приложения с библиотеками или службами (или разработчиками!), Вы можете столкнуться в будущем со сбоями, когда несколько элементов имеют одинаковый идентификатор - что является разумной возможностью, поскольку это технически недействительно. HTML.

Сила твоя!


Отличный ответ. всегда лучше, если вы будете придерживаться стандартов.
— EKanadily

25

Даже если элементы бывают разных типов, это может вызвать у вас серьезные проблемы ...

Предположим, у вас есть 3 кнопки с одинаковым идентификатором:

<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>

Теперь вы настраиваете jQueryкод, чтобы что-то делать при myidнажатии кнопок:

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

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

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

Чего бы вы ожидали? Каждая нажатая кнопка будет запускать установку обработчика событий щелчка с помощью jQuery. К сожалению, этого не произойдет. ТОЛЬКО первая кнопка вызывает обработчик щелчка. Остальные 2 при нажатии ничего не делают. Как будто они вовсе не были кнопками!

Так всегда назначать разные IDsдля HTMLэлементов. Это защитит вас от странных вещей. :)

<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>

Теперь, если вы хотите, чтобы обработчик события щелчка запускался при нажатии любой из кнопок, он будет отлично работать, если вы измените селектор в коде jQuery, чтобы использовать CSSкласс, примененный к ним следующим образом:

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

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

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

что, если у меня есть "#content", на который я уже ссылался в переменной, и # my-div #content, которое у меня есть только на несколько мгновений, после чего я удаляю указанный узел и забываю его переменную, после чего # div #content выполняет myDiv.outerHTML = myDiv.innerHTML для замены оригинала. Это избавляет от необходимости копировать все стили и содержимое #content в #decoy и делать то же самое. Это имеет смысл при выполнении переходов.
— Дмитрий

Это означает, что даже если я использую 'append' для добавления нескольких элементов с одинаковым идентификатором, DOM считает реальным только первый элемент, в идеале 1 ID = 1 элемент
— Karan Kaw

22

Нет. Два элемента с одинаковым идентификатором недопустимы. Идентификаторы уникальны, если вы хотите сделать что-то подобное, используйте класс. Не забывайте, что элементы могут иметь несколько классов, используя пробел в качестве разделителя:

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

12

Официальная спецификация для HTML гласит, что теги идентификаторов должны быть уникальными, И в официальной спецификации также говорится, что если рендеринг может быть завершен, он должен (т.е. в HTML нет такой вещи, как «ошибки», только «недействительный» HTML). Итак, ниже показано, как теги id работают на практике . Все они недействительны , но работают:

Этот:

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

Хорошо отображается во всех браузерах. Однако document.getElementById возвращает только объект, а не массив; вы сможете выбрать только первый div с помощью тега id. Если вы измените идентификатор первого div с помощью JavaScript, второй идентификатор будет доступен с помощью document.getElementById (проверено в Chrome, FireFox и IE11). Вы по-прежнему можете выбрать div, используя другие методы выбора, и его свойство id будет возвращено правильно.

Обратите внимание, что указанная выше проблема открывает потенциальную уязвимость безопасности на сайтах, которые отображают изображения SVG, поскольку SVG могут содержать элементы DOM, а также теги id на них (разрешает перенаправление DOM сценария через загруженные изображения). Пока SVG расположен в DOM перед заменяемым элементом, изображение будет получать все события JavaScript, предназначенные для другого элемента.

Насколько я знаю, эта проблема в настоящее время никого не интересует, но она реальна.

Этот:

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

Также отлично отображается во всех браузерах. Однако используется только первый идентификатор, который вы определяете таким образом, если вы пробовали document.getElementById ('unique-also'); в приведенном выше примере вам будет возвращено значение null (проверено в Chrome, FireFox и IE11).

Этот:

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

Также отлично отображается во всех браузерах, однако, в отличие от тегов классов, которые могут быть разделены пробелом, тег id допускает пробелы, поэтому идентификатор вышеуказанного элемента фактически равен «unique unique-two» и запрашивает у dom значение «unique» или «unique-two» изолированно возвращает null, если иное не определено где-либо в DOM (проверено в Chrome, FireFox и IE11).


1
«тег id допускает пробелы» - хотя, согласно спецификации , «значение не должно содержать пробелов».
— MrWhite

Согласен. Однако есть спецификация и то, как работают браузеры. Исторически браузеры рассматривали спецификацию как некую цель, но не были строги по многим параметрам. Я думаю, они делают это, потому что, если они соответствуют спецификации, это нарушит работу многих существующих сайтов или что-то в этом роде. Я упоминаю вверху, что, хотя эти вещи работают, они недействительны.
— Ник Стил

5

Ответ SLaks правильный, но в качестве дополнения обратите внимание, что в спецификациях x / html указано, что все идентификаторы должны быть уникальными в (одном) html-документе . Хотя это не совсем то, о чем спрашивал оператор, могут быть допустимые случаи, когда один и тот же идентификатор привязан к разным объектам на нескольких страницах.

Пример:

(обслуживается в современных браузерах) article # main-content {в одностороннем стиле }
(используется в устаревших версиях) div # main-content { в другом стиле }

Хотя, наверное, антипаттерн. Просто уйду отсюда как защитник дьявола.


1
Хорошая точка зрения. Хотя динамически генерируемый контент, который предполагается вставить на другую страницу, должен вообще избегать идентификаторов. Идентификаторы похожи на глобальные переменные в языках программирования, вы можете их использовать, и есть допустимые случаи, когда это хороший способ упрощения. Хорошая практика - подумать о том, чтобы сделать что-то правильно, прежде чем делать хаки.
— psycho brm

4

И чего бы это ни стоило, по крайней мере, в Chrome 26.0.1410.65, Firefox 19.0.2 и Safari 6.0.3, если у вас есть несколько элементов с одним и тем же идентификатором, селекторы jquery (по крайней мере) вернут первый элемент с этим идентификатором.

например

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

а также

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

См. Http://jsfiddle.net/RuysX/ для теста.


Если вы не используете более сложный селектор, такой как, div#oneконечно, это не меняет того факта, что он недействителен.
— Kevin B

Возможно, это правильный ответ, я говорю это на собственном опыте.
— Дибьяншу Джайсвал

4

Что ж, используя валидатор HTML на w3.org , специфичный для HTML5, идентификаторы должны быть уникальными.

Рассмотрим следующее ...

<!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>

валидатор отвечает ...

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>

... но в OP конкретно указано - как насчет разных типов элементов. Итак, рассмотрим следующий 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>

... результат валидатора ...

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

Вывод:

В любом случае (тот же тип элемента или другой тип элемента), если идентификатор используется более одного раза, он не считается допустимым HTML5.


2

Да, они могут.

Я не знаю, устарели ли все эти ответы, но просто откройте YouTube и проверьте HTML. Попробуйте просмотреть предложенные видео, вы увидите, что все они имеют одинаковый идентификатор и повторяющуюся структуру, как показано ниже:

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

1

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

var ids = document.getElementById('one');

идентификаторы содержат только первый элемент div. Таким образом, даже если есть несколько элементов с одинаковым идентификатором, объект документа вернет только первое совпадение.


1

Как насчет прагматичного ответа.

Заходим на YouTube и запускаем этот код

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))

и увидеть все повторяющиеся идентификаторы.

введите описание изображения здесь

Изменение приведенного выше кода для отображения идентификаторов, повторяющихся более 10 раз, вот список, который он создал

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

Другие сайты, которые используют один и тот же идентификатор более одного раза, включают Amazon.com, ebay.com, Expedia.com, cnn.com.

очевидно, что идентификаторы - это просто еще одна часть метаданных элемента.

getElementByIdв значительной степени устарело. Вы можете использовать querySelectorAllдля всех элементов или querySelectorдля первого, независимо от селектора, поэтому, если вам нужны все элементы с идентификатором, fooтогда

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

где, как если бы вы хотите использовать только первый элемент 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.

И мы видим, что с помощью селекторов мы можем находить разные элементы с одним и тем же идентификатором.

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>

Где важно, что идентификатор уникален

  • <a>Теги могут ссылаться на идентификаторы, как в <a href="#foo">. Щелчок по нему переместит документ к первому элементу с id="foo". Точно так же хэш-тег в URL-адресе, который фактически является той же функцией.

  • <label>Теги имеют forатрибут, который указывает, какой элемент они маркируют по идентификатору. Щелчок по метке щелкает / активирует / дает фокус соответствующему элементу. Метка повлияет только на первый элемент с совпадающим идентификатором

В противном случае idэто просто еще один инструмент в вашем наборе инструментов.


Интересный ответ, спасибо! Я наблюдал сгенерированные дублированные идентификаторы в каком-то стороннем коде (я забыл, что это было сейчас), и хотя я знал, что это будет работать в большинстве браузеров, мне было любопытно, есть ли какие-либо серьезные последствия / недостатки, и было ли это на самом деле действителен, поскольку в то время я считал, что он недействителен (и он все еще недействителен, но оказывается, что большинство клиентов снисходительны).
— omninonsense

Я бы сказал, что спецификация недействительна. Учитывая, что некоторые из крупнейших сайтов на планете используют эту функцию, спецификация должна измениться, чтобы отражать то, что на самом деле делают браузеры.
— gman

0

Возможно ли, чтобы в классе было более одного ученика с одинаковым номером Roll / Id? В HTML idатрибут вроде так. Вы можете использовать для них один и тот же класс. например:

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

И так далее.


-1

Нет, идентификаторы должны быть уникальными. Вы можете использовать классы для этой цели

<div class="a" /><div class="a b" /><span class="a" />

div.a {font: ...;}
/* or just: */
.a {prop: value;}

-1

Я думаю, вы не можете этого сделать, потому что Id уникален, вы должны использовать его для одного элемента. Вы можете использовать класс для этой цели


-1

Мы можем использовать имя класса вместо идентификатора. html id должен быть уникальным, а классы - нет. при извлечении данных с использованием имени класса можно уменьшить количество строк кода в ваших файлах js.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.