Specificity CSS: Kenapa Satu Aturan Menang dari yang Lain

Saat dua aturan CSS menyasar elemen yang sama, mana yang menang? Pelajari cara specificity dihitung, bagaimana ID, class, dan tag bersaing, di mana posisi !important serta inline style, dan cara menulis CSS yang gampang ditimpa.

Diterbitkan 4 Agustus 20268 menit bacaOleh ACY Partner Indonesia
Specificity CSS — bagaimana browser memilih aturan pemenang
300 × 250Slot Iklan TersediaPasang iklan Anda di sini

Kamu menulis sebuah aturan CSS, memuat ulang halaman, dan… tidak ada yang berubah. Warna yang kamu atur seperti tidak dianggap. Kamu tambahkan color: red, refresh, tapi teksnya tetap keras kepala berwarna biru. Tidak ada typo, selector-nya jelas cocok, tapi browser tetap saja tidak mau menurut.

Sembilan dari sepuluh kasus, biang keroknya adalah specificity — sistem yang dipakai CSS untuk menentukan aturan mana yang menang ketika beberapa aturan sama-sama menyasar elemen yang sama. Begitu kamu paham cara skornya dihitung, misteri “kok style-nya nggak nempel sih?!” itu kebanyakan langsung lenyap. Ini salah satu topik yang membedakan orang yang selalu berkutat melawan CSS dengan orang yang benar-benar menguasainya, jadi ayo kita tuntaskan.

Masalah yang dipecahkan specificity

CSS memungkinkan kamu menyasar elemen yang sama dari banyak sudut sekaligus. Satu paragraf bisa saja kena selector tag, selector class, sebuah ID, plus sesuatu yang diwarisi dari induknya — semuanya bersamaan, dan masing-masing mau mengatur warna yang berbeda:

p            { color: blue; }
.intro       { color: green; }
#first       { color: red; }
<p id="first" class="intro">Aku warnanya apa?</p>

Ketiga aturan itu sama-sama cocok dengan paragraf tersebut. Lalu warnanya jadi yang mana? Browser tidak bisa menerapkan ketiganya sekaligus, jadi ia butuh penentu. Penentu itulah specificity: cara menghitung seberapa spesifik tiap selector, di mana selector yang lebih spesifik akan menang.

Jawaban di sini adalah merah, karena ID itu lebih spesifik daripada class, dan class lebih spesifik daripada tag. Tapi supaya kamu bisa memprediksinya dengan yakin setiap saat, kamu perlu tahu bagaimana skornya benar-benar dihitung.

Cara specificity dihitung

Bayangkan specificity sebagai skor yang terdiri dari tiga kolom, ditulis seperti (a, b, c). Kamu tinggal menghitung isi selector-mu lalu mengisi kolom-kolomnya:

  • a — jumlah selector ID (#header)
  • b — jumlah selector class (.btn), selector atribut ([type="text"]), dan pseudo-class (:hover)
  • c — jumlah selector tipe/tag (div, p, h1) dan pseudo-element (::before)

Kolom yang lebih kiri selalu mengalahkan kolom di kanannya, berapa pun isinya. Kamu membandingkannya dari kiri ke kanan: yang ID-nya lebih banyak langsung menang; kalau seri di ID, baru bandingkan class; kalau itu pun seri, bandingkan selector tipe. Begini contoh skor beberapa selector:

p                  /* (0, 0, 1) — satu tag */
.intro             /* (0, 1, 0) — satu class */
#first             /* (1, 0, 0) — satu ID */
nav a              /* (0, 0, 2) — dua tag */
.menu a            /* (0, 1, 1) — satu class, satu tag */
#nav .item a       /* (1, 1, 1) — satu ID, satu class, satu tag */

Saat dua aturan bentrok, kamu baca skornya dari kiri ke kanan, dan angka yang lebih besar di kolom pertama yang berbeda itulah yang menang.

Kolomnya tidak naik tingkat seperti angka biasa

Specificity itu bukan basis 10. Skor (1, 0, 0) mengalahkan (0, 12, 0), walaupun dua belas class itu terasa lebih “banyak”. Satu ID mengungguli berapa pun jumlah class, dan satu class mengungguli berapa pun jumlah tag. Kolomnya tidak pernah saling menambah — sebelas class tidak akan pernah berakumulasi jadi satu ID. Bayangkan saja sebagai tiga kolom yang benar-benar terpisah, dibandingkan satu per satu mulai dari yang paling kiri.

Menelusuri satu perbandingan nyata

Mari kita selesaikan satu konflik beneran. Misalkan kamu punya markup ini dan dua aturan berikut:

<a class="button primary" href="/signup">Daftar</a>
.button        { background: gray; }   /* (0, 1, 0) */
.button.primary { background: blue; }  /* (0, 2, 0) */

Kedua selector sama-sama cocok dengan tautan itu. Yang pertama punya satu class, skornya (0, 1, 0). Yang kedua merangkai dua class sekaligus, skornya (0, 2, 0). Bandingkan dari kiri ke kanan: ID seri di angka 0, lalu masuk ke kolom class — 2 mengalahkan 1 — jadi aturan kedua yang menang, dan tombolnya jadi biru. Merangkai selector seperti .button.primary adalah cara yang rapi dan sengaja untuk membuat satu aturan lebih spesifik dari yang lain, tanpa perlu memakai ID atau !important.

Saat specificity seri

Apa yang terjadi kalau dua aturan punya specificity yang persis sama? Kalau begitu, specificity tidak bisa jadi penentu, dan CSS jatuh ke aturan cadangan: urutan penulisan. Aturan yang ditulis paling belakang di stylesheet-mu yang menang.

.btn { color: white; }
.btn { color: yellow; }  /* yang ini menang — ditulis lebih akhir */

Keduanya (0, 1, 0), benar-benar seri, jadi yang belakangan mengambil alih dan teksnya jadi kuning. Inilah kenapa urutan aturanmu itu penting, dan kenapa stylesheet yang dimuat belakangan bisa menimpa yang dimuat lebih dulu kalau selector-nya sama-sama spesifik. “Yang terakhir menang” berlaku setiap kali specificity-nya imbang.

Beginilah cascade bekerja

Kata “cascade” dalam Cascading Style Sheets merujuk persis ke proses ini: browser mengumpulkan semua aturan yang cocok dengan sebuah elemen, lalu mengurutkannya — pertama berdasarkan tingkat kepentingan, lalu specificity, dan terakhir urutan penulisan — untuk memilih satu pemenang per property. Specificity ada di tahap tengah, dan justru tahap inilah yang paling sering bikin orang tersandung.

Inline style dan posisinya

Ada satu tingkat lagi di atas semua yang sudah kita bahas: inline style, yaitu style yang ditulis langsung pada elemen lewat atribut style.

<p style="color: purple;">Aku di-style secara inline.</p>

Sebuah inline style itu lebih spesifik daripada selector apa pun yang bisa kamu tulis di stylesheet — bahkan mengalahkan selector ID sekalipun. Di model specificity lengkap, ia kadang ditulis sebagai kolom keempat yang paling kiri: (1, 0, 0, 0). Tapi yang perlu kamu ingat cukup ini: inline style mengalahkan CSS eksternal-mu, dan itulah persis alasan kenapa inline style susah banget ditimpa dan sebaiknya dihindari untuk hal yang ingin dipakai berulang. Kalau ada style yang “nggak mau berubah apa pun yang kamu lakukan”, coba cek apakah ada yang menyetelnya secara inline.

Pintu darurat !important

Bertengger di atas inline style sekalipun adalah !important. Tempelkan ini ke sebuah deklarasi, maka deklarasi tersebut langsung melompat ke puncak tangga prioritas, mengabaikan perbandingan specificity yang normal sama sekali:

.btn { color: white !important; }
#special { color: black; }   /* kalah, padahal pakai ID */

Di sini selector ID seharusnya menang, tapi !important menimpanya, jadi teks tombolnya tetap putih. Ini ibarat palu godam — dan justru di situlah masalahnya.

Anggap !important sebagai pilihan terakhir

!important memang berhasil, tapi ia jebakan. Begitu kamu pakai untuk memenangkan satu pertarungan, satu-satunya cara menimpanya lagi nanti adalah dengan !important yang lain, dan tak lama stylesheet-mu berubah jadi adu kekuatan yang tak bisa dipahami siapa pun. Ia membuang seluruh sistem specificity ke tempat sampah. Pakai hanya ketika kamu benar-benar tidak bisa mengubah CSS aslinya — misalnya saat menimpa library pihak ketiga yang tidak bisa kamu edit. Untuk kode buatanmu sendiri, lebih baik tata ulang selector-nya.

Universal selector dan combinator tidak menambah apa pun

Ada beberapa hal yang mungkin kamu kira ikut dihitung, padahal tidak. Universal selector (*) dan combinator (>, +, ~, serta spasi descendant) menyumbang nol ke specificity:

*              /* (0, 0, 0) — tidak menambah apa-apa */
ul > li        /* (0, 0, 2) — tanda > gratis, cuma dua tag */
.menu > .item  /* (0, 2, 0) — tanda > gratis, cuma dua class */

Jadi * adalah selector paling lemah yang ada — hampir apa pun bisa menimpanya — dan menaruh > atau + di antara dua selector tidak menaikkan skor sama sekali; yang dihitung hanya selector di kiri dan kanannya. Hal ini berguna kamu tahu saat sedang menebak aturan mana yang menang dan kebetulan melihat ada combinator di sana.

Menjaga specificity tetap rendah dan terkendali

Sekarang bagian yang paling berguna secara praktik. Kebiasaan terbaik untuk CSS yang sehat adalah menjaga specificity tetap rendah dan rata. Kalau sebagian besar aturanmu cuma satu class — semuanya duduk di (0, 1, 0) — menimpa salah satunya jadi gampang banget: tinggal tulis aturan satu-class lagi setelahnya. Masalah baru muncul ketika specificity merangkak naik gara-gara rangkaian selector yang panjang dan banyak ID, karena tiap penimpaan setelah itu harus lebih spesifik lagi, dan angkanya pun membengkak.

/* Susah ditimpa nanti — dalam dan penuh ID */
#sidebar ul li a.link { color: blue; }   /* (1, 1, 2) */

/* Gampang ditimpa nanti — datar dan berbasis class */
.sidebar-link { color: blue; }           /* (0, 1, 0) */

Keduanya bisa men-style tautan yang sama, tapi yang kedua jauh lebih ramah buat dirimu di masa depan. Beberapa kebiasaan ini membantu menjaga semuanya tetap datar:

  • Utamakan class daripada ID dan selector tag untuk styling. Class duduk di tingkat tengah yang nyaman dan gampang dilapis.
  • Jangan berlebihan menambah kualifikasi. .btn lebih baik daripada a.btn atau nav ul li .btn — selector ekstra cuma menggembungkan skor tanpa manfaat apa pun.
  • Hindari ID untuk styling. ID oke dipakai sebagai pegangan JavaScript atau target anchor, tapi specificity-nya yang tinggi bikin susah ditimpa di CSS.
  • Simpan !important untuk keadaan darurat, seperti saat berurusan dengan kode yang tidak bisa kamu edit.

Jaga specificity-mu tetap rendah dan rata, maka CSS berhenti terasa seperti pertarungan — penimpaan jadi langsung jalan, dan kamu jauh lebih sedikit menghabiskan waktu bertanya-tanya kenapa sebuah style tidak mau menempel.

Penutup

Specificity adalah penentu milik browser untuk memutuskan aturan CSS mana yang menang, dan sekarang kamu sudah tahu cara skornya dihitung:

  • Browser menghitung ID, lalu class (plus atribut dan pseudo-class), lalu selector tipe/tag ke dalam tiga kolom (a, b, c).
  • Kolom yang lebih tinggi selalu mengalahkan yang lebih rendah — satu ID mengungguli berapa pun jumlah class; kolomnya tidak pernah saling menambah.
  • Saat specificity seri, urutan penulisan yang menentukan: aturan cocok yang ditulis paling akhir menang.
  • Inline style mengalahkan selector apa pun, dan !important mengalahkan itu semua — tapi !important adalah pilihan terakhir.
  • Universal selector * dan combinator (>, +, ~) tidak menambah apa-apa ke skor.
  • Jaga specificity tetap rendah dan datar — andalkan single class — supaya CSS-mu tetap gampang ditimpa.

Topik ini berdiri langsung di atas pemahaman cara kerja selector, jadi kalau urusan mencocokkan elemen masih terasa goyah, ada baiknya kamu kembali dulu ke CSS selector dan apa itu CSS. Dengan specificity yang sudah kamu kuasai, kamu benar-benar pegang kendali atas style mana yang berlaku — dan itulah bedanya antara menebak-nebak dengan benar-benar paham.

Tag:cssfrontendspecificityselectormenengah
728 × 90Slot Iklan TersediaPasang iklan Anda di sini

Artikel Terkait

Lihat Semua Artikel

Artikel yang Mungkin Kamu Suka

Apa Itu Framework Frontend? — chip kode dengan tag komponen
Frontend / Dasar

Apa Itu Framework Frontend?

Penjelasan ramah untuk pemula tentang apa itu framework frontend, kenapa mereka ada, masalah apa yang mereka selesaikan dibanding JavaScript biasa, dan kapan kamu memang sebaiknya memakainya.

20 Sep 20268 menit baca
Sampul fundamentals frontend bertuliskan Apa Itu Frontend dan HTML + CSS + JS
Frontend / Dasar

Apa Itu Frontend Development?

Panduan ramah pemula tentang frontend development: bagian website yang kamu lihat dan klik secara langsung. Pahami cara kerja HTML, CSS, dan JavaScript, serta bedanya frontend dengan backend.

20 Sep 20268 menit baca
Ilustrasi sampul untuk Apa yang Dikerjakan Frontend Developer
Frontend / Dasar

Apa yang Dikerjakan Frontend Developer: Panduan untuk Pemula

Penjelasan ramah pemula tentang apa yang sebenarnya dikerjakan frontend developer setiap hari: mengubah desain jadi antarmuka yang berfungsi, membangun UI yang bisa dipakai ulang, sampai urusan responsif, aksesibilitas, dan kecepatan.

20 Sep 20269 menit baca
Kartu judul bertuliskan Styling dan Interaktivitas di atas latar biru gelap ACY Partner
Frontend / Dasar

Cara Kerja Styling dan Interaktivitas

Penjelasan ramah pemula soal bagaimana CSS menyulap HTML polos jadi tampilan rapi, dan bagaimana JavaScript menambahkan perilaku — pola berpikir struktur, gaya, perilaku saat membangun halaman web.

20 Sep 20268 menit baca
Tiga lapisan front-end menyatu di satu halaman web
Frontend / Dasar

Cara HTML, CSS, dan JavaScript Bekerja Bersama

Panduan praktis untuk pemula: bikin satu tombol kecil, beri struktur dengan HTML, tampilan dengan CSS, dan perilaku dengan JavaScript, lalu lihat ketiga lapisan ini bekerja sama di halaman nyata.

20 Sep 20268 menit baca
Sampul ikhtisar praktik terbaik frontend
Frontend / Dasar

Ikhtisar Praktik Terbaik Frontend

Peta ringkas tentang apa itu frontend yang baik — HTML bermakna, CSS rapi, JavaScript secukupnya, desain responsif, performa, dan progressive enhancement, lengkap dengan arahan untuk mendalaminya.

20 Sep 20268 menit baca