Idenya
Cepat atau lambat kamu akan menulis rule CSS dan tidak terjadi apa-apa. Hampir selalu, ada rule lain yang menang. Browser menyelesaikan konflik dengan algoritma yang tetap, cascade, dan begitu kamu tahu tiga langkah utamanya, "kenapa CSS-ku tidak jalan?" menjadi diagnosis cepat alih-alih tebak-tebakan.
Langkah 1: rule yang lebih belakang menang (kalau sama spesifiknya)
Mulai dari konflik paling sederhana. Dua rule sama-sama mengatur warna harga, dan keduanya memakai selector yang persis sama. Warna apa yang akhirnya dipakai harga itu?
<style>
.price { color: green; }
.price { color: #7a4b2a; }
</style>
<p class="price">Rp 95.000</p>
Dua rule dengan selector yang sama mengatur color. Yang muncul lebih belakang di stylesheet menang: cokelat. Ini juga berlaku antarfile: stylesheet yang ditautkan lebih belakang menimpa yang lebih awal.
Langkah 2: selector yang lebih spesifik menang
Sekarang rule-rule itu memakai selector yang berbeda, yang semuanya cocok dengan harga yang sama. Urutan tidak lagi menentukan. Sebelum membaca penjelasannya, coba tebak warna setiap harga:
<style>
#featured { color: purple; } /* 1 id */
.card .price { color: #7a4b2a; } /* 2 classes */
.price { color: green; } /* 1 class */
p { color: blue; } /* 1 type */
</style>
<article class="card" id="featured">
<p class="price">Rp 95.000</p>
</article>
<p class="price">Rp 120.000</p>
Specificity memberi skor pada setiap selector dengan menghitung tiga hal, dibandingkan dari kiri ke kanan seperti nomor versi:
| Selector | id | class, atribut, pseudo-class | tipe, pseudo-element | Skor |
|---|---|---|---|---|
p | 0 | 0 | 1 | 0-0-1 |
.price | 0 | 1 | 0 | 0-1-0 |
.card .price | 0 | 2 | 0 | 0-2-0 |
nav a:hover | 0 | 1 | 2 | 0-1-2 |
#featured | 1 | 0 | 0 | 1-0-0 |
Skor yang lebih tinggi menang, berapa pun urutannya. Satu id mengalahkan class sebanyak apa pun; satu class mengalahkan tipe sebanyak apa pun. Harga pertama berada di dalam #featured, tetapi #featured menargetkan article-nya, bukan paragrafnya, jadi rule milik paragraf itu sendiri yang menentukan: .card .price (0-2-0) mengalahkan .price (0-1-0) → cokelat. Harga kedua hanya cocok dengan .price dan p → hijau.
Inline style (style="..." pada elemen) mengalahkan selector apa pun, dan itulah salah satu alasan untuk menghindarinya.
Langkah 3: !important (dan kenapa harus dihindari)
color: red !important; melompat ke depan antrean, di atas semua deklarasi normal. Ini menggoda saat sebuah rule tidak mau berlaku, tetapi satu-satunya cara untuk menimpanya nanti adalah !important lain, dan stylesheet yang menempuh jalan itu menjadi mustahil dipahami. Simpan untuk kasus utilitas yang langka (seperti helper .hidden { display: none !important; }). Perbaikan yang lebih baik hampir selalu:
- turunkan specificity rule yang sedang kamu lawan (class alih-alih id), atau
- buat rule-mu sama specificity-nya dan letakkan lebih belakang.
Inheritance
Ada satu cara lagi sebuah elemen bisa mendapat gaya: dari elemen yang membungkusnya. Kalau kamu mengatur font di body, setiap paragraf dan heading di halaman memakainya, walaupun tidak ada rule yang langsung menargetkan mereka. Tapi tidak semua property bekerja seperti itu:
<style>
body { font-family: Georgia, serif; color: #333; line-height: 1.6; }
.card { border: 2px solid #7a4b2a; padding: 1rem; }
</style>
<div class="card">
<h2>Arabica Gayo</h2>
<p>Text inherits the font and colour from body, but not the card's border or padding.</p>
</div>
- Diwarisi: property yang berkaitan dengan teks:
color,font-family,font-size,font-weight,line-height,text-align,visibility. - Tidak diwarisi: property kotak:
border,padding,margin,background,width,display.
Itulah sebabnya kamu mengatur font sekali di body alih-alih di setiap elemen. Seorang anak bisa ikut mewarisi secara eksplisit dengan inherit (border: inherit;), dan kontrol formulir adalah jebakan yang umum: tombol dan input tidak mewarisi font secara default, jadi banyak stylesheet menambahkan button, input, select, textarea { font: inherit; }.
Saat rule berkonflik: specificity lebih tinggi menang (id > class > tipe); dengan specificity yang sama, rule yang lebih belakang menang. Hindari id dan !important di stylesheet supaya specificity tetap rendah dan mudah ditebak. Property teks diwarisi; property kotak tidak.
Men-debug rule yang "tidak jalan"
Buka developer tools (F12), pilih elemennya, dan lihat panel Styles: panel itu mendaftar setiap rule yang cocok dalam urutan cascade, dengan deklarasi yang kalah dicoret. Rule paling atas adalah pemenangnya, dan selector-nya memberitahumu cara mengalahkannya.
Mengapa ini penting untuk kode yang bersih
CSS yang mudah ditebak berasal dari specificity yang datar dan rendah: sebagian besar class tunggal (.card-title, bukan #main .content div h2). Dengan begitu urutan source saja yang menentukan konflik, rule mana pun bisa ditimpa oleh rule yang sedikit lebih belakang, dan kamu tidak pernah butuh !important. Cascade berhenti menjadi pertarungan dan berubah menjadi alat.
Rangkuman
- Specificity sama → rule yang lebih belakang menang.
- Specificity: id (1-0-0) > class/atribut/pseudo-class (0-1-0) > tipe (0-0-1); inline style mengalahkan semua selector.
!importantmenimpa semua yang lain; hindari.- Property teks diwarisi (
color,font-*,line-height); property kotak tidak (border,padding,margin,background). - Gunakan developer tools untuk melihat rule mana yang menang dan kenapa.