Dua elemen HTML dengan atribut id yang sama: Seberapa buruk itu sebenarnya?

122

Cukup browsing kode sumber google maps. Di header mereka, mereka memiliki 2 divs dengan id = "search" yang satu berisi yang lain, dan juga memiliki atribut jstrack = "1". Ada bentuk yang memisahkan mereka seperti ini:

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

Karena ini adalah google, saya menganggap itu bukan kesalahan.

Jadi seberapa burukkah itu bisa melanggar aturan ini? Selama Anda berhati-hati dalam pemilihan css dan dom Anda, mengapa tidak menggunakan kembali kelas seperti id? Adakah yang melakukan ini dengan sengaja, dan jika demikian, mengapa?

danludwig
sumber
102
"Karena ini google, aku menganggap itu bukan kesalahan." -> Google tidak bisa salah. Mereka membuat kesalahan seperti kita semua.
Joeri Sebrechts
43
sebenarnya orang-orang di google memiliki SEARCH melesat dalam pikiran mereka sehingga mereka tidak dapat memikirkan id lain: P
Pankaj Upadhyay
10
Saya merasa bahwa laman tersebut dibuat dari fragmen html yang berbeda sehingga satu pengembang dalam satu fragmen menggunakan id itu, dan hal yang sama terjadi dengan pengembang lain di fragmen lainnya.
Luciano
10
Seluruh pertanyaan "seburuk apa itu sebenarnya" hanya mengingatkan saya pada hal ini: xkcd.com/292
Daniel Roseman
3
@DanielRoseman xkcd juga melakukannya: what-if.xkcd.com/23/#question
SQB

Jawaban:

140

Spesifikasi mengatakan UNIK

Spesifikasi HTML 4.01 mengatakan ID harus unik untuk seluruh dokumen.

Spesifikasi HTML 5 mengatakan hal yang sama tetapi dengan kata lain. Dikatakan bahwa ID harus unik di subtree rumah , yang pada dasarnya adalah dokumen jika kita membaca definisi itu .

Hindari duplikasi

Tetapi karena penyaji HTML sangat memaafkan dalam hal rendering HTML, mereka mengizinkan ID duplikat. Ini harus dihindari jika mungkin dan benar - benar dihindari ketika mengakses elemen secara terprogram oleh ID dalam JavaScript. Saya tidak yakin getElementByIdfungsi apa yang harus dikembalikan ketika beberapa elemen yang cocok ditemukan? Haruskah itu:

  • kembalikan kesalahan?
  • kembalikan elemen pencocokan pertama?
  • kembalikan elemen pencocokan terakhir?
  • mengembalikan serangkaian elemen yang cocok?
  • tidak mengembalikan apa-apa?

Tetapi bahkan jika browser bekerja andal hari ini, tidak ada yang dapat menjamin perilaku ini di masa depan karena ini melanggar spesifikasi. Itu sebabnya saya sarankan Anda tidak pernah menggandakan ID dalam dokumen yang sama.

Robert Koritnik
sumber
1
@missingno: Saya menambahkan tautan ke spesifikasi HTML 5 yang berbicara tentang hal yang sama tetapi dengan kata-kata yang berbeda.
Robert Koritnik
6
Menurut spec DOM , "Jika lebih dari satu elemen memiliki atribut ID dengan nilai itu, apa yang dikembalikan adalah tidak terdefinisi" (yang artinya tidak ada hasil "benar" yang ditentukan, daripada nilai aktual undefined). Jarang ide yang baik untuk mengandalkan perilaku yang tidak terdefinisi.
lonesomeday
1
Perlu dicatat dengan HTML5, data-atribut ini berguna ketika seseorang mungkin tergoda untuk menetapkan beberapa hal ID yang sama. Ini memungkinkan Anda memiliki banyak ID berbeda dengan satu data-somethingatribut yang sama. Namun, semua browser yang saya tahu mengabaikan atribut yang tidak dikenal, jadi mereka mungkin aman di hampir setiap browser modern yang tidak memiliki dukungan HTML penuh.
Tim Post
2
@ JoachimSauer: Ketika Anda menggunakan atribut data Anda dapat memiliki pasangan nilai kunci yang tidak benar ketika Anda menggunakan kelas CSS. Dalam hal itu mereka semua seperti properti boolean. Suatu elemen memiliki kelas CSS atau tidak. Jika Anda ingin nilai dengan kelas CSS maka Anda harus menggabungkannya ke dalam nama kelas CSS dan menguraikannya setelah itu. Saya harap Anda sekarang dapat melihat manfaat dari menggunakan dataatribut. Dan mereka juga didukung langsung di luar kotak oleh jQuery ketika Anda cukup merujuk ke data-something="123"atribut $(elem).data("something").
Robert Koritnik
1
@RobertKoritnik: Tentu saja! Saya tidak memikirkan kasus penggunaan itu. Saya hanya memikirkan kasus id="search".
Joachim Sauer
30

Anda bertanya "seberapa buruk". Jadi untuk menyempurnakan jawabannya (sepenuhnya akurat) @ RobertKoritnik ...

Kode itu salah. Salah tidak datang dalam nuansa abu-abu. Kode ini melanggar standar dan karenanya salah. Ini akan gagal memeriksa validasi, dan seharusnya.

Yang mengatakan, tidak ada browser saat ini di pasaran akan mengeluh tentang hal itu, atau punya masalah sama sekali. Peramban berhak untuk mengeluh tentang hal itu, tetapi tidak ada versi saat ini dari mereka yang melakukannya. Yang tidak berarti versi yang akan datang mungkin tidak memperlakukan kode ini dengan buruk.

Perilaku Anda yang mencoba menggunakan ID itu sebagai pemilih, baik dalam css atau javascript, tidak dapat diabaikan dan mungkin bervariasi dari browser ke browser. Saya kira suatu penelitian dapat dilakukan untuk melihat bagaimana masing-masing browser bereaksi terhadap hal itu. Saya pikir dalam kasus terbaik, itu akan memperlakukannya seperti "class =", dan pilih daftar mereka. (Namun, itu mungkin membingungkan perpustakaan JavaScript - jika saya adalah penulis jQuery, saya mungkin telah mengoptimalkan kode pemilih saya sehingga jika Anda datang kepada saya dengan pemilih yang dimulai dengan "#", saya mengharapkan satu objek, dan mendapatkan daftar mungkin membuat saya benar-benar bork.)

Mungkin juga memilih yang pertama, atau mungkin yang terakhir, atau tidak memilih salah satu dari mereka, atau crash browser sepenuhnya. Tidak ada cara untuk mengatakannya tanpa mencobanya.

"Seberapa buruk" bergantung sepenuhnya pada seberapa ketat browser tertentu mengimplementasikan spesifikasi HTML, dan apa yang dilakukannya ketika dihadapkan dengan pelanggaran terhadap spesifikasi itu.

EDIT: SAYA HANYA kebetulan menemukan ini hari ini. Saya menarik berbagai komponen dari formulir pencarian pada berbagai jenis entitas untuk menghasilkan utilitas pelaporan lengkap all-in-one yang besar untuk situs ini, saya memuat formulir pencarian halaman jauh dalam div tersembunyi dan memasukkannya ke dalam pembuat laporan ketika tipe entitas yang sesuai dipilih sebagai sumber untuk laporan. Jadi ada versi tersembunyi formulir, dan versi yang ditampilkan di pembuat laporan. JavaScript yang datang dengan, dalam semua kasus, mengacu pada elemen dengan ID, yang sekarang ada DUA di halaman - yang tersembunyi, dan yang ditampilkan.

Apa yang tampaknya dilakukan jQuery adalah memilih saya yang PERTAMA, yang dalam semua kasus persis yang saya TIDAK inginkan.

Saya sedang mengerjakan ini dengan menulis penyeleksi untuk menentukan wilayah halaman yang saya inginkan untuk mendapatkan bidang saya (yaitu: $ ('# containerDiv #specificElement')). Tapi ada satu jawaban untuk pertanyaan Anda - jQuery on Chrome pasti berperilaku dengan cara tertentu ketika dihadapkan dengan pelanggaran spesifikasi ini.

Dan Ray
sumber
... pertanyaan terkait: stackoverflow.com/q/29295824/287948 tentang kewajiban ID dalam profil cepat CSS.
Peter Krauss
3
"Salah tidak datang dalam nuansa abu-abu." Saya melihat ini banyak dan itu salah satu hal yang secara teknis benar tetapi tidak "benar" dalam hidup atau dalam pemrograman. Anda secara tidak langsung membahas jawaban Anda dengan cukup teliti dan saya dapat menguraikannya tetapi adegan dari Teori Big Bang ini melakukan pekerjaan yang sangat baik sehingga saya akan membiarkannya berbicara untuk saya dan semoga membuat seseorang tertawa ... Stuart vs Sheldon youtube.com/ watch? v = F_1zoX5Ax9U
Night Owl
ini adalah jawaban 8 tahun, tapi saya pikir itu sangat tidak seimbang bagaimana Anda hiperbola pada pertanyaan OP namun tidak banyak mengeluh tentang perilaku permisif dan berbahaya browser tentang id berulang, yang jauh lebih buruk daripada apa yang coba OP lakukan.
erandros
20

Seberapa buruk itu sebenarnya?

  1. Itu membuatku sedih
  2. Itu tidak valid
  3. Banyak pustaka javascript tidak akan berfungsi seperti yang diharapkan
  4. Itu membuat kode Anda membingungkan

Pengalaman mengatakan bahwa getElementById di browser utama akan mengembalikan elemen yang cocok pertama dalam dokumen. Tapi ini mungkin tidak selalu terjadi di masa depan.

Ketika jQuery diberi id misalnya #foo, ia menggunakan getElementById dan meniru perilaku itu. Jika Anda harus mengatasi ini (itu menyedihkan), Anda dapat menggunakan $ (" * #foo") yang akan meyakinkan jQuery untuk menggunakan getElementsByTagName dan mengembalikan daftar semua elemen yang cocok.

Saya sering harus menulis kode untuk situs lain, dan saya harus mengatasinya. Dalam dunia yang adil, saya tidak perlu mendesain ulang fungsi untuk memulai dengan memeriksa apakah ID itu unik. ID harus selalu unik. Dunia ini kejam dan itulah sebabnya saya menangis.

ColBeseder
sumber
5
Jawaban ini membuat saya menangis ... tertawa!
A1rPun
8

Anda dapat melakukan banyak hal - tetapi itu tidak berarti Anda harus melakukannya.

Sebagai seorang programmer (secara umum) kita membangun hidup kita untuk menjadi tepat dan mengikuti aturan - ini adalah aturan yang mudah diikuti, yang cukup mendasar untuk apa yang kita lakukan - kita suka (tergantung pada) pengidentifikasi unik dalam lingkup yang diberikan ...

Melanggar aturan adalah sesuatu yang bisa kita lakukan karena browser terlalu akomodatif - tetapi sebenarnya kita semua akan lebih baik jika browser ketat tentang perlunya HTML yang terbentuk dengan baik dan valid, jumlah kecil rasa sakit yang akan ditimbulkannya sudah lama telah dilunasi!

Jadi, apakah ini benar-benar seburuk itu? Sebagai seorang programmer, bagaimana Anda bisa bertanya? Ini adalah kejahatan terhadap peradaban (-:


Tambahan:

Anda menulis bahwa browser terlalu akomodatif seolah itu hal yang buruk

Ya, karena - kita tidak berbicara tentang aturan yang rumit, kita berbicara secara substansial tentang membuat segala sesuatunya terbentuk dengan baik dan menerapkan aturan yang dapat diuji secara mekanis dan yang pada gilirannya membuatnya lebih mudah untuk hasilnya diproses secara mekanis. Jika browser ketat maka alat akan sangat cepat beradaptasi untuk mendukung itu - tidak demikian halnya, beberapa sejauh mereka mengeksploitasi yang gagal sebagai gantinya. Coba pikirkan ini - email akan menjadi media yang jauh lebih baik jika MS dan Netscape tidak mengacaukannya dengan mengizinkan HTML tidak dibatasi ketika "bahasa markup email" yang jauh lebih kompleks dengan dukungan eksplisit untuk teks yang dikutip akan memberi kita alat yang jauh lebih baik ... Tapi kapal itu berlayar dan kita juga bisa 'seharusnya ) tetapi kita tidak bisa

Murph
sumber
Anda menulis bahwa browser terlalu akomodatif seolah-olah itu hal yang buruk, tetapi pasti Anda tidak percaya itu?
KaptajnKold
4
Saya tidak dapat berbicara untuk Murph, tetapi saya pasti berpikir itu adalah hal yang sangat buruk. Kemudian lagi, tanpa tingkat pengampunan ini, web mungkin tidak memiliki dorongan untuk tumbuh seperti yang kita ketahui.
Andrea
1
@Andrea: Internet tidak akan tumbuh seperti yang kita tahu. Itu akan tumbuh lebih lambat. Tetapi itu juga akan memiliki dasar yang lebih kuat dari apa yang ada dan tidak kode yang benar. Cepat-tetapi-ceroboh dapat bekerja, tapi saya lebih suka lebih lambat-tapi-benar. Terutama karena tidak seperti kita hanya akan berbicara tentang beberapa tahun pertumbuhan atau lebih.
Nicol Bolas
3
@Andrea Saya berani bertaruh bahwa itu akan tumbuh hampir secepat - alat hanya akan berevolusi untuk mengatasi masalah. Padahal dalam banyak kasus alat tersebut adalah akar penyebab markup yang buruk. Faktanya adalah bahwa orang cenderung melakukan yang paling tidak diperlukan - langkah untuk "terbentuk dengan baik" adalah langkah yang relatif kecil dan cukup mudah untuk diuji dan ditegakkan dan orang akan mengakomodasi itu tanpa tekanan yang signifikan
Murph
1
Tidak mengerikan bahwa browser mengakomodasi. SANGAT mengerikan bahwa mereka semua akomodatif dengan cara yang berbeda .
Dan Ray
7

Di Scripting: getElementByIDhanya akan mengembalikan kecocokan pertama. Di CSS: #idakan memengaruhi SEMUA elemen dengan ID itu. Di Browser Render tidak akan berpengaruh apa pun.

Ini adalah perilaku standar w3c. Bukan yang mungkin, itu yang didefinisikan facto.

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

Bart Calixto
sumber
7
Ini adalah salah satu perilaku yang mungkin. getElementByIddapat dengan sempurna mengembalikan elemen apa pun, atau bahkan objek nol. Efek CSS bisa pada elemen apa saja, atau tidak ada atau semuanya. Atau browser bisa macet. Di luar standar, perilaku tidak terdefinisi
rds
2
Itu tidak keluar dari standar karena standar menentukan apa yang harus dilakukan dalam situasi itu. Jadi tidak, getElementById tidak dapat mengembalikan elemen apa pun, standar mengatakan secara eksplisit bahwa saya akan mengembalikan pertandingan pertama. Saya setuju bahwa perilaku di luar standar tidak terdefinisi, yang tidak Anda pahami adalah bahwa semua kasus adalah bagian dari standar.
Bart Calixto
1
Jawaban ini akan sedikit lebih baik jika itu benar-benar termasuk, sebagai referensi, kutipan dari bagian yang relevan dari standar (atau setidaknya nomor bagian).
yoniLavi
2
@yoniLavi diperbarui.
Bart Calixto
2
Terima kasih @ Bart. Anda memang benar :) Standar mengatakan "Mengembalikan elemen pertama dalam keturunan simpul yang ID-nya adalah elementId."
yoniLavi