Zwei HTML-Elemente mit demselben ID-Attribut: Wie schlimm ist es wirklich?

122

Durchsuchen Sie einfach den Google Maps-Quellcode. In ihrer Kopfzeile haben sie 2 Divs mit id = "search", eine enthält die andere, und sie haben auch das Attribut jstrack = "1". Es gibt eine Form, die sie so trennt:

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

Da dies Google ist, gehe ich davon aus, dass es kein Fehler ist.

Wie schlimm kann es also wirklich sein, gegen diese Regel zu verstoßen? Solange Sie bei der Auswahl von CSS und Dom vorsichtig sind, können Sie ids wie Klassen wiederverwenden. Tut dies jemand absichtlich und wenn ja, warum?

danludwig
quelle
102
"Da dies Google ist, gehe ich davon aus, dass es kein Fehler ist." -> Google sind nicht unfehlbar. Sie machen Fehler wie der Rest von uns.
Joeri Sebrechts
43
Tatsächlich haben sich die Jungs von google SEARCH in den Kopf gesetzt, sodass sie sich keine anderen
Pankaj Upadhyay
10
Ich habe das Gefühl, dass diese Seite aus verschiedenen HTML-Fragmenten gerendert wird, sodass ein Entwickler in einem Fragment diese ID verwendet hat, und dasselbe geschah mit anderen Entwicklern im anderen Fragment.
Luciano
10
Die ganze Frage "Wie schlimm ist es wirklich" erinnert mich nur daran: xkcd.com/292
Daniel Roseman
3
@DanielRoseman xkcd macht es auch: what-if.xkcd.com/23/#question
SQB

Antworten:

140

Spezifikation sagt EINZIGARTIG

Gemäß der HTML 4.01-Spezifikation muss die ID dokumentweit eindeutig sein.

Die HTML 5-Spezifikation sagt dasselbe, aber mit anderen Worten. Es besagt, dass ID in seinem Heimat-Teilbaum eindeutig sein muss , was im Grunde genommen das Dokument ist, wenn wir dessen Definition lesen .

Vermeide Dopplungen

Da HTML-Renderer in Bezug auf HTML-Rendering jedoch sehr nachsichtig sind, lassen sie doppelte IDs zu. Dies sollte nach Möglichkeit vermieden werden und beim programmgesteuerten Zugriff auf Elemente durch IDs in JavaScript unbedingt vermieden werden . Ich bin nicht sicher, welche getElementByIdFunktion zurückgegeben werden soll, wenn mehrere übereinstimmende Elemente gefunden werden? Sollte es:

  • Einen Fehler zurückgeben?
  • Erstes passendes Element zurückgeben?
  • Letztes passendes Element zurückgeben?
  • eine Reihe von übereinstimmenden Elementen zurückgeben?
  • nichts zurückgeben?

Aber selbst wenn Browser heutzutage zuverlässig funktionieren, kann niemand dieses Verhalten in Zukunft garantieren, da dies der Spezifikation widerspricht. Aus diesem Grund empfehle ich, dass Sie niemals IDs innerhalb desselben Dokuments duplizieren .

Robert Koritnik
quelle
1
@missingno: Ich habe einen Link zur HTML 5-Spezifikation hinzugefügt, der sich auf das gleiche Thema bezieht, jedoch in einem anderen Wortlaut.
Robert Koritnik
6
Gemäß der DOM-Spezifikation ist "Wenn mehr als ein Element ein ID-Attribut mit diesem Wert hat, ist das zurückgegebene Ergebnis undefiniert" (was bedeutet, dass kein definiertes "korrektes" Ergebnis vorliegt und nicht der tatsächliche Wert undefined). Es ist selten eine gute Idee, sich auf undefiniertes Verhalten zu verlassen.
Lonesomeday
1
Es ist erwähnenswert, dass das data-Attribut in HTML5 nützlich ist, wenn man versucht sein könnte, mehreren Dingen dieselbe ID zuzuweisen. Auf diese Weise haben Sie viele verschiedene IDs mit einem gemeinsamen data-somethingAttribut. Trotzdem ignorieren alle mir bekannten Browser unbekannte Attribute, so dass sie wahrscheinlich in nahezu jedem modernen Browser ohne vollständige HTML-Unterstützung sicher sind.
Tim Post
2
@JoachimSauer: Wenn Sie Datenattribute verwenden, können Sie Schlüssel-Wert-Paare haben, was bei Verwendung von CSS-Klassen nicht der Fall ist. In diesem Fall sind sie alle wie boolesche Eigenschaften. Ein Element hat entweder eine CSS-Klasse oder keine. Wenn Sie Werte mit CSS-Klassen wollen, müssen Sie diese irgendwie zu CSS-Klassennamen kombinieren und diese anschließend analysieren. Ich hoffe, Sie können jetzt die Vorteile der Verwendung von dataAttributen sehen. Und sie werden von jQuery auch sofort unterstützt, wenn Sie einfach auf data-something="123"attribute with verweisen $(elem).data("something").
Robert Koritnik
1
@RobertKoritnik: Natürlich! Ich habe nicht an diesen Anwendungsfall gedacht. Ich habe nur an den Fall gedacht id="search".
Joachim Sauer
30

Sie fragten "wie schlimm". Also, um @ RobertKoritniks (vollkommen genaue) Antwort ein wenig zu präzisieren ...

Dieser Code ist falsch. Falsch kommt nicht in Graustufen. Dieser Code verstößt gegen den Standard und ist daher falsch. Die Validierungsprüfung würde fehlschlagen, und das sollte auch so sein.

Das heißt, kein Browser auf dem Markt würde sich darüber beschweren oder überhaupt ein Problem damit haben. Browser hätten das Recht , sich darüber zu beschweren, aber keine der aktuellen Versionen von ihnen tut dies derzeit. Dies bedeutet nicht, dass zukünftige Versionen diesen Code möglicherweise nicht schlecht behandeln.

Ihr Verhalten, wenn Sie versuchen, diese ID als Selektor in CSS oder Javascript zu verwenden, ist nicht zu erraten und variiert wahrscheinlich von Browser zu Browser. Ich nehme an, dass eine Studie durchgeführt werden könnte, um zu sehen, wie jeder Browser darauf reagiert. Ich denke, im besten Fall würde es wie "class =" behandelt und die Liste ausgewählt. (Dies könnte jedoch die JavaScript - Bibliotheken verwirren. Wenn ich der Autor von jQuery wäre, hätte ich möglicherweise meinen Auswahlcode so optimiert, dass ich ein einzelnes Objekt erwarte und ein Liste könnte mich komplett verpfuschen.)

Es kann auch das erste oder möglicherweise das letzte oder keines davon auswählen oder den Browser vollständig zum Absturz bringen. Keine Möglichkeit zu sagen, ohne es zu versuchen.

"Wie schlecht" hängt dann ganz davon ab, wie streng ein bestimmter Browser die HTML-Spezifikation implementiert und was er tut, wenn er mit einer Verletzung dieser Spezifikation konfrontiert wird.

EDIT: Das habe ich gerade heute gesehen. Ich rufe verschiedene Komponenten von Suchformularen auf verschiedenen Arten von Entitäten ab, um ein großartiges All-in-One-Berichtsdienstprogramm für diese Site zu erstellen. Ich lade die Suchformulare der Remote-Seiten in versteckten Divs hoch und füge sie in meine ein Berichtsgenerator, wenn der entsprechende Entitätstyp als Quelle für den Bericht ausgewählt wurde. Es gibt also eine versteckte Version des Formulars und eine Version, die im Berichtsgenerator angezeigt wird. Das mitgelieferte JavaScript bezieht sich in jedem Fall auf Elemente nach ID, von denen sich jetzt ZWEI auf der Seite befinden - das versteckte und das angezeigte.

Was jQuery zu tun scheint, ist, mich als ERSTEN auszuwählen, was in jedem Fall genau das ist, was ich NICHT will.

Ich arbeite daran, indem ich Selektoren schreibe, um den Bereich der Seite anzugeben, in den ich mein Feld einfügen möchte (dh: $ ('# containerDiv #specificElement')). Aber es gibt eine Antwort auf Ihre Frage: jQuery auf Chrome verhält sich bei dieser Verletzung der technischen Daten auf jeden Fall anders.

Dan Ray
quelle
... eine verwandte Frage: stackoverflow.com/q/29295824/287948 über die Verpflichtung von IDs in einem schnellen CSS-Profil.
Peter Krauss
3
"Falsch kommt nicht in Graustufen." Ich sehe das sehr oft und es ist eines der Dinge, die technisch korrekt sind, aber im Leben oder in der Programmierung nicht "wahr" sind. Du behandelst das indirekt ziemlich gründlich in deiner Antwort und ich könnte es erklären, aber diese Szene aus der Urknalltheorie leistet so gute Arbeit, dass ich sie für mich sprechen lassen und hoffentlich jemanden zum Lachen bringen werde ... Stuart vs Sheldon youtube.com/ watch? v = F_1zoX5Ax9U
Night Owl
Dies ist eine 8-jährige Antwort, aber ich denke, es ist sehr unausgewogen, wie sehr Sie die Frage von OP übertreiben, aber Sie beklagen sich nicht über das freizügige und gefährliche Verhalten von Browsern in Bezug auf wiederholte IDs, was viel schlimmer ist als das, was OP versucht.
Erandros
20

Wie schlimm ist es wirklich?

  1. Das bringt mich zum Weinen
  2. Es ist ungültig
  3. Viele Javascript-Bibliotheken funktionieren nicht wie erwartet
  4. Es macht Ihren Code verwirrend

Erfahrungsgemäß gibt getElementById in gängigen Browsern das erste übereinstimmende Element im Dokument zurück. Dies ist in Zukunft jedoch möglicherweise nicht immer der Fall.

Wenn jQuery eine ID, z. B. #foo, erhält, verwendet es getElementById und ahmt dieses Verhalten nach. Wenn Sie das umgehen müssen (das ist traurig), können Sie $ (" * #foo") verwenden, was jQuery davon überzeugt, getElementsByTagName zu verwenden und eine Liste aller übereinstimmenden Elemente zurückzugeben.

Ich muss oft Code für andere Sites schreiben und das muss ich umgehen. In einer gerechten Welt müsste ich Funktionen nicht neu gestalten, um zunächst zu überprüfen, ob eine ID eindeutig ist. IDs sollten immer eindeutig sein. Die Welt ist grausam und deshalb weine ich.

ColBeseder
quelle
5
Diese Antwort brachte mich zum Weinen ... vor Lachen!
A1rPun,
8

Sie können sehr viele Dinge tun - aber das bedeutet nicht, dass Sie sollten.

Als Programmierer (im Allgemeinen) bauen wir unser Leben darauf, präzise zu sein und die Regeln zu befolgen - hier ist eine Regel, die einfach zu befolgen ist, die ziemlich grundlegend für unser Handeln ist - wir mögen (abhängig von) eindeutigen Bezeichnern innerhalb eines bestimmten Bereichs ...

Die Regel zu brechen ist etwas, das wir tun können, weil der Browser viel zu entgegenkommend ist - aber wirklich, wir alle wären besser dran, wenn die Browser strikt darauf bedacht wären, wohlgeformtes und gültiges HTML zu benötigen zurückgezahlt worden!

Also ist es wirklich so schlimm? Wie kann man als Programmierer überhaupt fragen? Es ist ein Verbrechen gegen die Zivilisation (-:


Nachtrag:

Sie schreiben, dass Browser zu entgegenkommend sind, als dass es eine schlechte Sache wäre

Ich tue es, weil es so ist - wir reden nicht über komplizierte Regeln, wir reden wesentlich darüber, Dinge gut zu formen und auf andere Weise Regeln anzuwenden, die mechanisch getestet werden können und die wiederum die mechanische Verarbeitung des Ergebnisses erleichtern. Wenn die Browser streng gewesen wären, hätten sich die Tools sehr schnell darauf eingestellt - das war nicht der Fall, manche in dem Maße, in dem sie diesen Fehler ausnutzen. Denken Sie nur einmal darüber nach - E-Mails wären ein viel besseres Medium gewesen, wenn MS und Netscape nicht uneingeschränktes HTML zugelassen hätten, wenn eine weitaus weniger komplexe "E-Mail-Auszeichnungssprache" mit expliziter Unterstützung für zitierten Text uns ein weitaus besseres Werkzeug gegeben hätte ... aber das Schiff ist gesegelt und in ähnlicher Weise können wir 'sollte haben ), aber wir können nicht

Murph
quelle
Sie schreiben, dass Browser zu entgegenkommend sind, als dass es eine schlechte Sache wäre, aber Sie glauben das doch nicht?
KaptajnKold
4
Ich kann nicht für Murph sprechen, aber ich denke sicher, dass es eine wirklich schlechte Sache ist. Andererseits hätte das Web ohne dieses Maß an Vergebung möglicherweise nicht den Impuls gehabt, so zu wachsen, wie wir es kennen.
Andrea
1
@ Andrea: Das Internet wäre nicht so gewachsen, wie wir es kennen. Es wäre langsamer gewachsen. Es hätte aber auch eine solidere Grundlage für den korrekten Code. Fast-but-Sloppy mag funktionieren, aber ich bevorzuge langsamer, aber korrekt. Zumal es nicht so ist, als würden wir nur über ein paar Jahre Wachstum sprechen.
Nicol Bolas
3
@Andrea Ich wette, dass es fast so schnell gewachsen wäre - die Tools hätten sich einfach weiterentwickelt, um das Problem zu lösen. In vielen Fällen waren die Tools die Hauptursache für schlechte Markups. Tatsache ist, dass die Leute dazu neigen, das Wenigste zu tun - der Schritt zu "gut geformt" ist relativ klein und leicht zu testen und durchzusetzen, und die Leute hätten das ohne nennenswerten Stress in
Kauf genommen
1
Es ist nicht schrecklich, dass Browser entgegenkommen. Es ist schrecklich, dass sie alle auf unterschiedliche Weise entgegenkommen .
Dan Ray
7

In Scripting: getElementByIDGibt nur die erste Übereinstimmung zurück. In CSS: #idBetrifft ALLE Elemente mit dieser ID. Im Browser hat Render keine Auswirkung.

Dies ist das Verhalten des W3C-Standards. Kein möglicher, sondern der faktisch definierte.

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

Bart Calixto
quelle
7
Dies ist ein mögliches Verhalten. getElementByIdkönnte perfekt jedes Element oder sogar ein Null-Objekt zurückgeben. Der CSS-Effekt kann auf beliebige Elemente oder auf keines oder alle Elemente angewendet werden. Oder der Browser könnte abstürzen. Außerhalb des Standards ist das Verhalten undefiniert
am
2
Es ist nicht von der Norm abweichend, da die Norm angibt, was in diesen Situationen zu tun ist. Also nein, getElementById konnte kein Element zurückgeben, der Standard sagt explizit, dass ich die erste Übereinstimmung zurückgeben werde. Ich stimme zu, dass ein Verhalten außerhalb des Standards undefiniert ist. Was Sie nicht verstehen, ist, dass all diese Fälle Teil des Standards sind.
Bart Calixto
1
Diese Antwort wäre etwas besser, wenn sie tatsächlich als Referenz ein Zitat des relevanten Teils der Norm (oder zumindest eine Abschnittsnummer) enthalten würde.
yoniLavi
2
@yoniLavi aktualisiert.
Bart Calixto
2
Vielen Dank @Bart. Sie haben vollkommen recht :) Der Standard sagt "Gibt das erste Element innerhalb der Nachkommen des Knotens zurück, dessen ID elementId ist."
YoniLavi