Specificity dan Cascade
Definisi
Cascade adalah mekanisme browser untuk menentukan deklarasi CSS mana yang akhirnya dipakai ketika beberapa aturan menargetkan elemen yang sama.
Specificity adalah bobot prioritas selector. Semakin spesifik selector, semakin besar peluang deklarasinya menang saat ada konflik.
Keduanya bekerja bersama. Cascade memilih sumber aturan yang paling layak dibandingkan aturan lain, lalu specificity dipakai untuk memecahkan konflik di level selector.
Kenapa penting
Banyak bug CSS bukan karena properti salah, tetapi karena aturan yang benar kalah prioritas. Gejalanya biasanya seperti ini:
- style tidak berubah walau selector sudah ditulis
- komponen library sulit dioverride
- aturan baru hanya bekerja setelah pakai
!important - CSS terasa "acak" karena urutan file memengaruhi hasil
Kalau mekanisme ini dipahami, debugging CSS menjadi jauh lebih cepat. Kamu tidak lagi menebak-nebak selector mana yang menang, tetapi bisa menghitungnya.
Urutan keputusan browser
Saat beberapa deklarasi bersaing, browser biasanya mengevaluasi prioritas dalam urutan berikut:
!important- asal stylesheet dan layer, jika digunakan
- specificity selector
- urutan deklarasi yang muncul belakangan
Pada praktik modern, urutan ini bisa dipengaruhi juga oleh @layer. Tetapi untuk kasus sehari-hari, tiga hal yang paling sering menentukan adalah:
- apakah deklarasinya
!important - seberapa spesifik selector-nya
- aturan mana yang ditulis terakhir
Specificity: cara menghitung bobot
Specificity biasanya dirangkum sebagai tiga angka:
inline styles, id, class/attribute/pseudo-class, element/pseudo-elementContoh perbandingan:
#header .nav alebih kuat daripada.nav a.card .titlelebih kuat daripada.titlebuttonlebih lemah daripada.button
Aturan umum yang berguna:
- selector berbasis
idsangat kuat - class, attribute selector, dan pseudo-class punya bobot menengah
- elemen dan pseudo-element punya bobot paling rendah
- inline style berada di atas selector biasa
Contoh hitung cepat
#app .card .title {
color: blue;
}
.card .title {
color: red;
}Selector pertama menang karena memiliki id.
Jika dipecah:
#app .card .title→0,1,2,0.card .title→0,0,2,0
Walaupun jumlah class sama, adanya id membuat selector pertama lebih kuat.
Cascade: apa yang dilakukan browser
Cascade bukan hanya "siapa yang paling spesifik". Browser juga mempertimbangkan sumber deklarasi dan urutan kemunculan.
Artinya, dua selector yang sama kuat tetap bisa menghasilkan hasil berbeda tergantung mana yang ditulis terakhir.
.button {
background: blue;
}
.button {
background: green;
}Hasil akhirnya adalah green, karena selector sama kuat dan deklarasi terakhir menang.
Alur prioritas CSS
Diagram ini menyederhanakan proses browser. Detail implementasi bisa lebih panjang, tetapi alurnya tetap sama: browser menyaring prioritas, lalu membandingkan bobot selector, lalu memakai urutan terakhir sebagai penentu akhir.
Contoh konflik yang sering terjadi
1. Selector terlalu umum
p {
color: gray;
}
.article p {
color: black;
}Di halaman biasa, paragraf di dalam .article akan mengikuti aturan kedua karena selector-nya lebih spesifik.
2. Utility class kalah karena selector lain lebih berat
.text-red {
color: red;
}
.card .content .text-red {
color: blue;
}Walaupun utility class terlihat "cukup jelas", selector kedua menang karena specificity-nya lebih tinggi.
3. !important dipakai sebagai jalan pintas
.alert {
color: red !important;
}!important memang memaksa prioritas naik, tetapi sering membuat CSS sulit dirawat. Kalau dipakai terus-menerus, override berikutnya menjadi makin mahal.
Penjelasan praktis
Specificity sebaiknya dipakai sebagai alat desain struktur CSS, bukan sekadar trik menang konflik.
Pola yang lebih sehat biasanya seperti ini:
- gunakan selector yang cukup sederhana
- beri nama class yang jelas dan konsisten
- hindari chaining selector terlalu dalam
- gunakan
!importanthanya untuk kasus yang benar-benar terisolasi - jika project memakai
@layer, kelompokkan aturan berdasarkan peran, bukan berdasarkan kebiasaan menumpuk file
Dengan cara ini, prioritas CSS menjadi mudah ditebak. Developer baru tidak perlu menelusuri selector berlapis-lapis hanya untuk mengganti warna tombol.
Implementasi yang berguna
1. Mulai dari selector rendah
Gunakan class sebagai basis utama:
.button {
padding: 0.75rem 1rem;
border-radius: 0.5rem;
}Selector seperti ini mudah dioverride tanpa perang specificity.
2. Naikkan spesifik hanya saat perlu
Kalau ingin variasi komponen, tambahkan modifier class:
.button--primary {
background: royalblue;
color: white;
}Ini lebih aman daripada menulis selector yang bergantung pada struktur DOM yang dalam.
3. Hindari selector yang terlalu panjang
/* kurang ideal */
.sidebar .menu li a span {
font-weight: 600;
}Selector panjang membuat override sulit dan rapuh terhadap perubahan HTML.
4. Jadikan urutan file sebagai alat yang disengaja
Kalau dua aturan memang setara, taruh aturan yang ingin menang di bawah.
Jebakan umum
- Menganggap aturan terakhir selalu menang, padahal specificity bisa mengalahkan urutan.
- Menggunakan
!importantuntuk menutupi struktur CSS yang tidak rapi. - Menulis selector sangat panjang hanya agar "pasti menang".
- Lupa bahwa class, attribute, dan pseudo-class dihitung lebih tinggi daripada elemen biasa.
- Mengira inline style sama dengan stylesheet biasa; inline style punya bobot sendiri.
- Mengabaikan
@layer, lalu bingung kenapa library CSS terasa "lebih kuat" atau "lebih lemah" dari yang diperkirakan.
Catatan implementasi
- Gunakan DevTools untuk melihat aturan mana yang dicoret dan mana yang aktif.
- Kalau override gagal, cek specificity sebelum mengganti kode.
- Simpan aturan dasar di level yang rendah, lalu tambah variasi lewat class tambahan.
- Hindari perang selector antara file global dan komponen.
- Dokumentasikan pola prioritas CSS yang dipakai tim agar konsisten.
Istilah
- Cascade: proses pemilihan deklarasi CSS yang menang ketika ada konflik.
- Specificity: bobot prioritas selector.
- Origin: sumber aturan CSS, misalnya user agent, author, atau user stylesheet.
- Layer: lapisan prioritas CSS yang bisa diatur dengan
@layer. !important: penanda untuk menaikkan prioritas deklarasi.- Override: mengganti nilai CSS yang sudah ada.
- Selector chaining: menumpuk beberapa selector untuk menaikkan spesifisitas.