web-dev-qa-db-fra.com

Deux éléments HTML avec le même attribut id: à quel point est-ce vraiment mauvais?

Il suffit de parcourir le code source de google maps. Dans leur en-tête, ils ont 2 divs avec id = "search" l'un contient l'autre, et a également l'attribut jstrack = "1". Il y a un formulaire les séparant comme ceci:

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

Puisque c'est google, je suppose que ce n'est pas une erreur.

Alors, à quel point peut-il être grave de violer cette règle? Tant que vous êtes prudent dans votre sélection css et dom, pourquoi ne pas réutiliser les classes similaires à id? Quelqu'un le fait-il exprès, et si oui, pourquoi?

128
danludwig

La spécification dit UNIQUE

spécification HTML 4.01 indique que l'ID doit être unique à l'échelle du document.

spécification HTML 5 dit la même chose mais en d'autres termes. Il dit que l'ID doit être unique dans son home subtree, qui est fondamentalement le document si nous lisez sa définition .

Évitez les doublons

Mais comme les rendus HTML sont très indulgents en ce qui concerne le rendu HTML, ils autorisent les ID en double. Cela doit être évité si possible et strictement évité lors de l'accès par programmation aux éléments par ID en JavaScript. Je ne sais pas quelle fonction getElementById doit retourner lorsque plusieurs éléments correspondants sont trouvés? Devrait-il:

  • retourner une erreur?
  • retourner le premier élément correspondant?
  • retourner le dernier élément correspondant?
  • retourner un ensemble d'éléments correspondants?
  • rien retourner?

Mais même si les navigateurs fonctionnent de manière fiable de nos jours, personne ne peut garantir ce comportement à l'avenir, car cela est contraire aux spécifications. C'est pourquoi je vous recommande de ne jamais dupliquer les ID dans le même document.

146
Robert Koritnik

Vous avez demandé "à quel point". Donc, pour étoffer la réponse de RobertKoritnik (entièrement exacte) un peu ...

Ce code est incorrect. Incorrect ne vient pas dans les tons de gris. Ce code viole la norme et est donc incorrect. Cela échouerait à la vérification de la validation, et cela devrait.

Cela dit, aucun navigateur actuellement sur le marché ne s'en plaindrait ou n'aurait aucun problème avec cela. Les navigateurs seraient dans leurs droits pour s'en plaindre, mais aucune des versions actuelles de l'un d'entre eux ne le fait actuellement. Ce qui ne veut pas dire que les futures versions pourraient ne pas mal traiter ce code.

Votre comportement en essayant d'utiliser cet ID comme sélecteur, en CSS ou en Javascript, est impossible à deviner et varie probablement d'un navigateur à l'autre. Je suppose qu'une étude pourrait être effectuée pour voir comment chaque navigateur réagit à cela. Je pense que dans le meilleur des cas, il le traiterait comme "class =" et en sélectionnerait la liste. (Cela pourrait toutefois confondre les bibliothèques JavaScript - si j'étais l'auteur de jQuery, j'aurais peut-être optimisé mon code de sélecteur de sorte que si vous venez à moi avec un sélecteur commençant par "#", j'attends un seul objet et obtenant un la liste pourrait me bouleverser complètement.)

Il peut également sélectionner le premier, ou éventuellement le dernier, ou n'en sélectionner aucun, ou bloquer complètement le navigateur. Pas moyen de le dire sans l'essayer.

"How bad" dépend alors entièrement de la rigueur avec laquelle un navigateur particulier implémente la spécification HTML et de ce qu'il fait lorsqu'il est confronté à une violation de cette spécification.

EDIT: Je viens de rencontrer cela aujourd'hui. Je récupère divers composants des formulaires de recherche sur différents types d'entités pour produire un grand utilitaire de rapport tout-en-un pour ce site, je charge les formulaires de recherche des pages distantes dans des divs cachés et les insère dans mon générateur de rapports lorsque le type d'entité approprié est sélectionné comme source pour le rapport. Il existe donc une version cachée du formulaire et une version affichée dans le générateur de rapports. Le JavaScript fourni avec, dans tous les cas, se réfère aux éléments par ID, dont il y a maintenant DEUX sur la page - celui caché et celui affiché.

Ce que jQuery semble faire, c'est me sélectionner le PREMIER, qui dans tous les cas est exactement celui que je NE VEUX PAS.

Je travaille autour de cela en écrivant des sélecteurs pour spécifier la région de la page dans laquelle je veux obtenir mon champ (par exemple: $ ('# containerDiv #specificElement')). Mais il y a une réponse à votre question - jQuery sur Chrome se comporte certainement d'une manière particulière lorsqu'il est confronté à cette violation des spécifications.

31
Dan Ray

Est-il si mal que ca?

  1. Ça me fait pleurer
  2. C'est invalide
  3. De nombreuses bibliothèques javascript ne fonctionneront pas comme prévu
  4. Cela rend votre code déroutant

L'expérience montre que getElementById dans les principaux navigateurs retournera le premier élément correspondant dans le document. Mais ce ne sera pas toujours le cas à l'avenir.

Lorsque jQuery reçoit un identifiant, par exemple #foo, il utilise getElementById et imite ce comportement. Si vous devez contourner cela (c'est triste), vous pouvez utiliser $ ("* # foo") qui convaincra jQuery d'utiliser getElementsByTagName et renverra une liste de tous les éléments correspondants.

Je dois souvent écrire du code pour d'autres sites, et je dois contourner cela. Dans un monde juste, je n'aurais pas à repenser les fonctions pour commencer en vérifiant si un ID est unique. Les identifiants doivent toujours être uniques. Le monde est cruel et c'est pourquoi je pleure.

22
ColBeseder

Vous pouvez faire beaucoup de choses - mais cela ne signifie pas que vous devriez le faire.

En tant que programmeur (en général), nous construisons notre vie en étant précis et en suivant les règles - voici une règle simple à suivre, qui est assez fondamentale pour ce que nous faisons - nous comme (dépend de ) identificateurs uniques dans une portée donnée ...

Enfreindre la règle est quelque chose que nous pouvons faire parce que le navigateur est beaucoup trop accommodant - mais vraiment nous serions tous mieux si les navigateurs étaient stricts à propos d'avoir besoin d'un HTML bien formé et valide, le peu de douleur qu'il aurait causé aurait depuis longtemps été remboursé!

Alors, est-ce vraiment si mauvais? En tant que programmeur, comment pouvez-vous même demander? C'est un crime contre la civilisation (-:


Addenda:

Vous écrivez que les navigateurs sont trop accommodants comme si c'était une mauvaise chose

Je le fais, parce que c'est - nous ne parlons pas de règles compliquées, nous parlons essentiellement de rendre les choses bien formées et d'appliquer autrement des règles qui peuvent être testées mécaniquement et qui à leur tour facilitent le traitement mécanique du résultat. Si les navigateurs avaient été stricts, les outils se seraient très rapidement adaptés à cela - ce n'était pas le cas, certains dans la mesure où ils exploitaient cet échec à la place. Pensez-y un peu - l'e-mail aurait été un bien meilleur moyen si MS et Netscape ne l'avaient pas bousillé en autorisant un HTML illimité alors qu'un "langage de balisage d'e-mail" beaucoup moins complexe avec un support explicite pour le texte cité nous aurait donné un bien meilleur outil ... mais ce navire a navigué et de la même manière, nous ne pouvons pas fermer la porte stable sur ce que les navigateurs permettent (nous devrait, HTML5 devrait avoir) mais nous ne pouvons pas

8
Murph

Dans Scripting: getElementByID renverra uniquement la première correspondance. En CSS: #id affectera TOUS les éléments avec cet ID. Dans le navigateur, le rendu n'aura aucun effet.

C'est le comportement de la norme w3c. Pas possible, c'est celui défini de facto.

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

7
Bart Calixto