Ini bug yang bikin saya curiga sama CSS selama satu jam penuh, padahal masalahnya sama sekali bukan di CSS. Di sebuah situs editorial yang saya bangun, grid card artikel tiba-tiba kolaps: tiap card mengecil jadi kolom selebar satu huruf, dan tiap kata di judul turun ke barisnya sendiri secara vertikal. Anehnya, gambar di dalam card lebarnya masih normal — yang berantakan cuma judul dan byline.
Saya mengutak-atik grid-template-columns, min-width, flex-basis, semuanya. Tidak ada yang berubah. Ternyata akar masalahnya ada di HTML, bukan CSS: saya tanpa sengaja menaruh <a> di dalam <a>, dan browser diam-diam membongkar struktur itu.
Kenapa anchor bersarang menghancurkan grid
HTML5 melarang anchor bersarang. <a> adalah elemen interaktif, dan spesifikasi tidak mengizinkan konten interaktif di dalam konten interaktif lain. Masalahnya, browser tidak menampilkan error — ia "memperbaiki" markup-nya sendiri.
Card saya kira-kira seperti ini: seluruh card dibungkus <a> agar bisa diklik, lalu di dalamnya ada <a> lagi untuk nama penulis (link ke halaman author). Saat parser bertemu <a> kedua, ia menutup paksa <a> pertama tepat di titik itu. Akibatnya, semua elemen setelah link author — judul, byline, sisa konten — tidak lagi berada di dalam anchor pembungkus. Mereka "naik" jadi anak langsung dari elemen grid.
Dan di sinilah grid kolaps. Anak grid yang tidak punya penempatan eksplisit otomatis dapat col-span-1. Jadi judul yang tadinya membentang penuh sekarang dijejalkan ke satu track kolom sempit, dan teksnya pecah per kata.
Diagnostik yang paling cepat membuktikannya: cek parent dari elemen judul di DevTools.
// Kalau outer link di-unwrap, parent h3 bukan lagi <a>
document.querySelector(".card h3").parentElement.tagName;
// Diharapkan: "A" → Kenyataan: "ARTICLE" (anchor pembungkus hilang)Begitu hasilnya "ARTICLE" bukan "A", jelas: browser sudah membongkar anchor luar saya.
Markup yang bermasalah
<a href="/article/slug" class="card">
<img src="/cover.webp" alt="" />
<h3>Judul artikel yang panjang</h3>
<!-- INI biang keroknya: anchor di dalam anchor -->
<a href="/author/jane">Jane Doe</a>
<time>9 Juni 2026</time>
</a>Begitu parser sampai ke <a href="/author/jane">, ia menutup .card anchor. <h3>, <time>, dan link author jadi saudara langsung di dalam grid — bukan lagi anak dari card yang bisa diklik.
Solusi: link dalam bukan <a>, tapi <span> dengan data-href
Kita tetap butuh dua tujuan klik berbeda: klik card ke artikel, klik nama ke halaman author. Triknya, jangan pakai dua anchor. Buat link dalam sebagai elemen non-interaktif yang kita beri perilaku link manual:
<a href="/article/slug" class="card">
<img src="/cover.webp" alt="" />
<h3>Judul artikel yang panjang</h3>
<!-- Bukan <a>, jadi anchor luar tidak di-unwrap -->
<span data-href="/author/jane" role="link" tabindex="0">Jane Doe</span>
<time>9 Juni 2026</time>
</a>Karena <span> bukan konten interaktif, browser tidak lagi menutup paksa anchor luar. Strukturnya utuh, grid kembali normal. Lalu kita pasang satu handler delegasi di dokumen untuk menghidupkan data-href:
// Klik pada elemen ber-data-href → navigasi, dan jangan picu card link
document.addEventListener("click", (e) => {
const link = e.target.closest("[data-href]");
if (!link) return;
e.preventDefault();
e.stopPropagation(); // cegah anchor card ikut ter-trigger
window.location.href = link.dataset.href;
});
// Keyboard: span role="link" harus respons Enter dan Space
document.addEventListener("keydown", (e) => {
if (e.key !== "Enter" && e.key !== " ") return;
const link = e.target.closest("[data-href]");
if (!link) return;
e.preventDefault();
e.stopPropagation();
window.location.href = link.dataset.href;
});stopPropagation() penting: tanpanya, klik nama author akan menggelembung ke anchor card dan membawa user ke artikel, bukan ke halaman author. role="link" dan tabindex="0" mengembalikan aksesibilitas yang hilang saat kita berhenti memakai <a> asli — elemen bisa difokus dengan keyboard dan diumumkan sebagai link oleh screen reader, lalu keydown menangani Enter/Space seperti anchor sungguhan.
Catatan tambahan
- Diagnostik tercepat tetap di DevTools: kalau
parentElement.tagNameelemen dalam bukan yang Anda kira, kemungkinan besar ada elemen interaktif yang di-unwrap browser. Ini juga berlaku untuk<button>di dalam<a>, atau<a>di dalam<button>. - Pola "card besar bisa diklik + satu link kecil di dalamnya" memang sering. Solusi alternatif: jadikan card bukan anchor (pakai overlay pseudo-element
::afterdenganposition: absolute; inset: 0), lalu link author tetap<a>asli yang diberiposition: relative; z-index: 1agar berada di atas overlay. Itu menjaga semantik anchor untuk keduanya. - Selalu validasi HTML saat layout "berantakan tanpa sebab". Validator akan langsung menandai "Element a not allowed as child of element a" — petunjuk yang lebih cepat daripada mengubek CSS satu jam.
Intinya: kalau grid kolaps dan CSS Anda kelihatan benar, periksa apakah browser sudah diam-diam menulis ulang DOM Anda. Anchor bersarang adalah salah satu cara paling halus markup yang "kelihatan benar" berubah jadi struktur yang sama sekali berbeda saat di-parse.
