Due elementi HTML con lo stesso attributo id: Quanto è grave?


122

Basta sfogliare il codice sorgente di google maps. Nella loro intestazione, hanno 2 div con id = "search" l'uno contiene l'altro e ha anche l'attributo jstrack = "1". C'è una forma che li separa così:

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

Dal momento che questo è google, presumo che non sia un errore.

Quindi quanto può essere davvero grave violare questa regola? Fintanto che stai attento nella tua selezione di CSS e DOM, perché non riutilizzare le classi ID? Qualcuno lo fa apposta, e se sì, perché?


102
"Dato che si tratta di Google, presumo che non sia un errore." -> Google non è infallibile. Commettono errori come il resto di noi.
Joeri Sebrechts,

43
in realtà i ragazzi di google hanno inchiodato CERCA nelle loro menti quindi non riescono a pensare a nessun altro id: P
Pankaj Upadhyay,

10
Ho la sensazione che quella pagina sia renderizzata da diversi frammenti HTML, quindi uno sviluppatore in un frammento ha usato quell'id, e lo stesso è accaduto con altri sviluppatori nell'altro frammento.
Luciano,

10
L'intera domanda di "quanto è veramente brutto" mi ricorda questo: xkcd.com/292
Daniel Roseman,

3
@DanielRoseman xkcd lo fa anche: what-if.xkcd.com/23/#question
SQB

Risposte:


140

Le specifiche dicono UNICHE

La specifica HTML 4.01 afferma che l'ID deve essere univoco a livello di documento.

La specifica HTML 5 dice la stessa cosa ma in altre parole. Dice che l'ID deve essere univoco nella sua sottostruttura principale , che è fondamentalmente il documento se ne leggiamo la definizione .

Evitare la duplicazione

Ma poiché i renderer HTML perdonano molto quando si tratta di rendering HTML, consentono ID duplicati. Questo dovrebbe essere evitato se possibile e rigorosamente evitato quando si accede a livello di codice di elementi tramite ID in JavaScript. Non sono sicuro di quale getElementByIdfunzione debba essere restituita quando vengono trovati più elementi corrispondenti? Dovrebbe:

  • restituire un errore?
  • restituisce il primo elemento corrispondente?
  • restituisce l'ultimo elemento corrispondente?
  • restituire un set di elementi corrispondenti?
  • non restituire niente?

Ma anche se i browser funzionano in modo affidabile in questi giorni, nessuno può garantire questo comportamento in futuro poiché è contro le specifiche. Ecco perché ti consiglio di non duplicare mai ID all'interno dello stesso documento.


1
@missingno: ho aggiunto un collegamento alla specifica HTML 5 che parla della stessa cosa ma con una diversa formulazione.
Robert Koritnik,

6
Secondo la specifica DOM , "Se più di un elemento ha un attributo ID con quel valore, ciò che viene restituito è indefinito" (ciò significa che non esiste un risultato "corretto" definito, piuttosto che il valore effettivo undefined). Raramente è una buona idea fare affidamento su comportamenti indefiniti.
lunedì

1
Vale la pena notare con HTML5, l' data-attributo è utile per quando si potrebbe essere tentati di assegnare a più cose lo stesso ID. Ciò ti consente di avere molti ID diversi con un data-somethingattributo comune in comune. Tuttavia, tutti i browser che conosco ignorano attributi sconosciuti, quindi sono probabilmente sicuri in quasi tutti i browser moderni privi del supporto HTML completo.
Tim Post

2
@JoachimSauer: quando usi gli attributi dei dati puoi avere coppie chiave-valore che non sono vere quando usi le classi CSS. In quel caso sono tutti come proprietà booleane. Un elemento ha una classe CSS oppure no. Se desideri valori con le classi CSS, dovresti in qualche modo combinarli nel nome della classe CSS e analizzarli in seguito. Spero che ora tu possa vedere i vantaggi dell'uso degli dataattributi. E sono anche supportati direttamente da jQuery quando si fa semplicemente riferimento data-something="123"all'attributo con $(elem).data("something").
Robert Koritnik,

1
@RobertKoritnik: Certo! Non ho pensato a quel caso d'uso. Ho pensato solo al caso di id="search".
Joachim Sauer,

30

Hai chiesto "quanto male". Quindi per dare un tocco in più alla risposta di RobertKoritnik (del tutto accurata) ...

Quel codice non è corretto. L'errato non arriva nei toni del grigio. Questo codice viola lo standard ed è quindi errato. Non verrebbe verificato il controllo di convalida e dovrebbe.

Detto questo, nessun browser attualmente sul mercato se ne lamenterebbe o non avrebbe avuto alcun problema. I browser avrebbero il diritto di lamentarsene, ma nessuna delle versioni attuali di nessuno di essi attualmente lo fa. Ciò non significa che le versioni future potrebbero non trattare male questo codice.

Il tuo comportamento nel tentativo di utilizzare quell'ID come selettore, sia in CSS che in JavaScript, non è indovinabile e probabilmente varia da browser a browser. Suppongo che uno studio potrebbe essere fatto per vedere come ogni browser reagisce a questo. Penso che nel migliore dei casi, lo tratterebbe proprio come "class =", e selezionerebbe l'elenco di essi. (Ciò potrebbe confondere le librerie JavaScript, tuttavia - se fossi l'autore di jQuery, avrei potuto ottimizzare il mio codice selettore in modo che se vieni da me con un selettore che inizia con "#", mi aspetto un singolo oggetto e ottengo un oggetto la lista potrebbe darmi una botta completamente.)

Potrebbe anche selezionare il primo, o forse l'ultimo, oppure non selezionarne nessuno, oppure bloccare completamente il browser. Non c'è modo di dirlo senza provarlo.

"Quanto male" dipende quindi interamente da quanto rigorosamente un particolare browser implementa le specifiche HTML e da cosa fa quando si confronta con una violazione di tali specifiche.

EDIT: SOLO mi è capitato di imbattermi oggi. Sto estraendo vari componenti dai moduli di ricerca su vari tipi di entità per produrre una grande utility di reporting all-in-one per questo sito, sto caricando i moduli di ricerca delle pagine remote in div nascosti e inserendoli nel mio generatore di report quando viene selezionato il tipo di entità appropriato come origine per il report. Quindi c'è una versione nascosta del modulo e una versione visualizzata nel generatore di report. Il codice JavaScript fornito, in ogni caso, si riferisce a elementi per ID, di cui ora sono DUE nella pagina: quella nascosta e quella visualizzata.

Quello che jQuery sembra fare è selezionarmi il PRIMO, che in ogni caso è esattamente quello che NON voglio.

Sto lavorando a questo problema scrivendo i selettori per specificare la regione della pagina in cui voglio inserire il mio campo (ovvero: $ ('# containerDiv #specificElement')). Ma c'è una risposta alla tua domanda: jQuery su Chrome si comporta sicuramente in un modo particolare di fronte a questa violazione delle specifiche.


... una domanda correlata: stackoverflow.com/q/29295824/287948 sull'obbligo degli ID in un profilo rapido CSS.
Peter Krauss,

3
"L'errato non arriva nei toni del grigio." Lo vedo molto ed è una di quelle cose che è tecnicamente corretta ma non "vera" nella vita o nella programmazione. Lo copri indirettamente abbastanza accuratamente nella tua risposta e potrei esporlo, ma questa scena di The Big Bang Theory fa un ottimo lavoro che lascerò che parli per me e spero che qualcuno rida ... Stuart vs Sheldon youtube.com/ guarda? v = F_1zoX5Ax9U
Night Owl

questa è una risposta di 8 anni, ma penso che sia molto sbilanciato il modo in cui iperboli sulla domanda di OP, ma non ti lamenti molto del comportamento permissivo e pericoloso dei browser su ID ripetuti, che è molto peggio di ciò che OP sta cercando di fare.
erandros,

20

Quanto è davvero grave?

  1. Mi fa piangere
  2. Non è valido
  3. Molte librerie javascript non funzioneranno come previsto
  4. Rende il tuo codice confuso

L'esperienza dice che getElementById nei principali browser restituirà il primo elemento corrispondente nel documento. Ma questo potrebbe non essere sempre il caso in futuro.

Quando a jQuery viene assegnato un ID, ad esempio #foo, utilizza getElementById e imita quel comportamento. Se devi aggirare questo (è triste), puoi usare $ (" * #foo") che convincerà jQuery a usare getElementsByTagName e restituirà un elenco di tutti gli elementi corrispondenti.

Spesso devo scrivere codice per altri siti e devo aggirare questo problema. In un mondo giusto, non avrei dovuto riprogettare le funzioni per iniziare controllando se un ID è univoco. Gli ID dovrebbero essere sempre univoci. Il mondo è crudele ed è per questo che piango.


5
Questa risposta mi ha fatto piangere ... dalle risate!
A1rPun

8

È possibile fare molte cose - ma questo non significa che si dovrebbe.

Come programmatore (in generale) costruiamo le nostre vite sull'essere precisi e seguendo le regole - ecco una regola che è semplice da seguire, che è abbastanza fondamentale per quello che facciamo - ci piace (dipende da) identificatori univoci all'interno di un determinato ambito ...

Infrangere la regola è qualcosa che possiamo fare perché il browser è troppo accomodante - ma davvero staremmo tutti meglio se i browser fossero severi sulla necessità di avere un HTML ben formato e valido, la piccola quantità di dolore che avrebbe causato avrebbe da tempo stato rimborsato!

Quindi, è davvero così male? Come programmatore come puoi anche chiedere? È un crimine contro la civiltà (-:


Addendum:

Scrivi che i browser sono troppo accomodanti come se fosse una brutta cosa

Sì, perché non stiamo parlando di regole complicate, stiamo parlando sostanzialmente di rendere le cose ben formate e di applicare in altro modo regole che possono essere testate meccanicamente e che a loro volta rendono più semplice l'elaborazione meccanica del risultato. Se i browser fossero stati severi, gli strumenti si sarebbero adattati molto rapidamente per supportarlo - non è stato così, alcuni nella misura in cui sfruttano invece quel fallimento. Basti pensare a questo: l'e-mail sarebbe stata un mezzo molto più bello se MS e Netscape non avessero rovinato tutto consentendo l'HTML senza restrizioni quando un "linguaggio di markup e-mail" molto meno complesso con supporto esplicito per il testo citato ci avrebbe fornito uno strumento molto migliore ... ma quella nave salpò e allo stesso modo possiamo 'dovrebbe avere ) ma non possiamo


Scrivi che i browser sono troppo accomodanti come se fosse una brutta cosa, ma sicuramente non ci credi?
KaptajnKold,

4
Non posso parlare per Murph, ma di sicuro penso che sia davvero una brutta cosa. Inoltre, senza questo livello di perdono, la rete potrebbe non avere avuto l'impulso di crescere come lo conosciamo.
Andrea,

1
@Andrea: Internet non sarebbe cresciuto come lo conosciamo. Sarebbe cresciuto più lentamente. Ma avrebbe anche avuto una base più solida di ciò che è e non è il codice corretto. Veloce ma sciatto può funzionare, ma preferisco di gran lunga più lento ma corretto. Soprattutto dal momento che non è che parleremo solo di un paio d'anni di crescita o giù di lì.
Nicol Bolas,

3
@Andrea Scommetto che sarebbe cresciuto quasi altrettanto velocemente - gli strumenti si sarebbero semplicemente evoluti per affrontare il problema. Considerando che in molti casi gli strumenti sono stati la causa principale del markup scadente. Il fatto è che le persone tendono a fare il meno necessario - il passo per "ben formato" è relativamente piccolo e abbastanza facile da testare e far rispettare e le persone avrebbero potuto accontentarlo senza stress significativo
Murph,

1
Non è orribile che i browser siano accomodanti. È orribile che siano tutti accomodanti in modi diversi .
Dan Ray,

7

In Scripting: getElementByIDrestituirà solo la prima corrispondenza. In CSS: #idinteresserà TUTTI gli elementi con quell'ID. In Browser Render non avrà alcun effetto.

Questo è il comportamento dello standard w3c. Non è possibile, è quello definito di fatto.

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


7
Questo è un possibile comportamento. getElementByIdpotrebbe restituire perfettamente qualsiasi elemento, o anche un oggetto null. L'effetto CSS potrebbe essere su qualsiasi elemento, o nessuno o tutti. Oppure il browser potrebbe bloccarsi. Fuori della norma, il comportamento è indefinito
RDS

2
Non è fuori dallo standard perché lo standard specifica cosa fare in quelle situazioni. Quindi no, getElementById non ha potuto restituire alcun elemento, lo standard dice esplicitamente che restituirò la prima corrispondenza. Sono d'accordo che il comportamento fuori dallo standard non è definito, ciò che non capisci è che tutti questi casi fanno parte dello standard.
Bart Calixto,

1
Questa risposta sarebbe in qualche modo migliore se effettivamente includesse, come riferimento, una citazione della parte pertinente della norma (o almeno un numero di sezione).
yoniLavi,

2
@yoniLavi aggiornato.
Bart Calixto,

2
Grazie @Bart. Hai assolutamente ragione :) Lo standard dice "Restituisce il primo elemento all'interno dei discendenti del nodo il cui ID è elementId."
yoniLavi,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.