Selector dasar nyamperin elemen berdasarkan tag, class, atau id. Tapi gimana kalo kamu mau lebih spesifik — misalnya "cuma paragraf yang JADI ANAK LANGSUNG dari div ini, bukan paragraf di nested section di dalamnya"? Disinilah combinator masuk — simbol kecil ( , >, +, ~) yang nyatuin dua selector dengan aturan hubungan tertentu. Power gede buat targeting presisi tanpa nambahin class baru.
💡 Spasi sebagai operator. Combinator descendant (
) itu sebenernya spasi — dia operator yang nyaru jadi pemisah..parent .child(ada spasi) = nested descendant..parent.child(gak ada spasi) = elemen yang punya KEDUA class. Salah pencet space bar = makna beda total.
1. Descendant (spasi) — semua keturunan:
div p { color: red; } /* semua p di dalam div */
2. Child (>) — anak langsung saja:
div > p { color: blue; } /* hanya p yang langsung di dalam div */
3. Adjacent sibling (+) — elemen tepat setelahnya:
h1 + p { color: green; } /* p pertama setelah h1 */
4. General sibling (~) — semua saudara setelahnya:
h1 ~ p { color: orange; } /* semua p setelah h1 (level yang sama) */
🎭 Analogi sehari-hari
Bayangin kamu pengen kasih hadiah ke anggota keluarga — tapi spesifik banget kriterianya. Combinator itu kayak panduan filter relationship: descendant ( ) = "semua keturunan ke bawah, anak-cucu-cicit"; child (>) = "anak kandung saja, gak termasuk cucu"; adjacent (+) = "saudara persis sebelah aku berdiri"; general sibling (~) = "semua adik yang lebih muda dari aku". Semakin spesifik kombinasi, semakin tepat targetnya — power gede buat styling tanpa nambah class.
⚠️ Jebakan yang sering ditemui
- Spasi (descendant) dalam selector matters —
.parent.child(no space) = elemen punya KEDUA class..parent .child(space) = nested. +cuma SATU saudara setelahnya, langsung.~semua saudara setelah.- Combinator + class rapat —
div>pvalid (no space around>). - Performance — selectors panjang dengan banyak combinator = browser harus walk DOM lebih jauh. Modern browsers handle baik, tapi simplify kalau bisa.
~general sibling tidak bisa "previous" — CSS tidak punya prev sibling.:has()untuk parent/sibling backwards.
TL;DR: Combinators = simbol nyatuin dua selector dengan aturan hubungan. Descendant (spasi A B) — semua keturunan. Child (A > B) — anak langsung saja. Adjacent sibling (A + B) — saudara tepat setelahnya. General sibling (A ~ B) — semua saudara setelahnya. Spasi matters: .parent.child (no space) = elemen punya 2 class, .parent .child (space) = nested. CSS gak punya prev sibling — pakai :has() buat parent/backward.