Kupas CSS: Cascade dan Inheritance
Proses peramban menentukan nilai akhir dari properti CSS yang diterapkan ke suatu elemen HTML.
Di artikel ini
CSS (Cascading Style Sheets) adalah bahasa yang digunakan untuk mendeskripsikan presentasi atau tampilan suatu elemen yang ditulis pada dokumen HTML. Suatu elemen HTML bisa dideskripsikan tampilannya oleh banyak property CSS yang berasal dari berbagai sumber dan cara implementasinya. User agents akan menentukan property CSS mana yang akan benar-benar diterapkan pada suatu elemen tersebut. Mekanisme penentuan tersebut wajib kita pahami agar dapat menulis CSS dengan baik dan memanfaatkan fitur-fiturnya. Aku pun baru bisa benar-benar memahaminya setelah menulis CSS selama bertahun-tahun.
Di tulisan ini, aku akan bercerita mengenai sifat-sifat dasar CSS yang juga merupakan mekanisme penentuan nilai akhir dari property CSS. Aku akan mengawali cerita ini dengan potongan kode dari cuitan kuis dari Mas Max Stoiber yang kurang lebih seperti ini isinya:
Mengapa demikian? MARKIBAS! Mari kita bahas!
Istilah
Untuk menyamakan pemahaman, ada beberapa istilah dalam CSS yang perlu kita pahami terlebih dahulu. Diketahui potongan kode seperti berikut.
Dari potongan kode tersebut di atas, ada beberapa hal yang bisa kita perhatikan:
-
Selector: digunakan untuk mendefinisikan elemen-elemen yang akan kita deskripsikan tampilannya. Pada potongan kode tersebut,
p
dan.text
adalah selector-nya. -
Property: atribut tampilan yang akan diatur. Pada potongan kode tersebut, property yang akan diatur adalah
color
danfont-size
. -
Declaration: terdiri dari pasangan property dan nilainya. Property
color
memiliki nilaiaqua
danfont-size
memiliki nilai16px
. -
Rule: potongan kode CSS di atas kita sebut sebagai CSS rule, terdiri dari selector dan beberapa CSS declaration yang ditulis di antara dua kurung kurawal.
-
Style Sheet: kumpulan dari beberapa CSS rule yang ditempatkan pada suatu berkas tertentu dan digunakan untuk mendeskripsikan tampilan elemen-elemen pada dokumen HTML.
-
User Agents: program komputer yang bisa menerjemahkan kode CSS dan HTML untuk ditampilkan ke penggunanya. Dalam kasus web, user agents-nya adalah peramban, misalnya Google Chrome dan Mozilla Firefox.
Sifat Cascade dari CSS
Sebuah elemen HTML bisa secara sekaligus ditarget oleh beberapa CSS rule yang mungkin memiliki beberapa declaration yang sama. Setiap CSS rule tersebut bisa berasal dari berbagai macam sumber dan cara penulisan. Sifat cascade dari CSS mengharuskan user agents (peramban) untuk menggabungkan semua CSS rule dan menentukan nilai akhir dari suatu property yang paling diprioritaskan dan pada akhirnya diterapkan ke setiap elemen dalam dokumen HTML. Cascade merupakan sifat utama dari CSS yang bahkan disematkan sebagai bagian dari kepanjangannya, Cascading Style Sheet. Untuk bisa menulis CSS dengan baik, kita harus bisa memahami sifat cascade tersebut.
Terdapat tiga kriteria yang digunakan dalam proses cascading:
- Order and origin
- Specificity
- Penggunaan
!important
.
Order and Origin
Kriteria pertama yang digunakan dalam proses cascading adalah order (urutan) penulisannya. Secara sederhana, jika terdapat lebih dari satu declaration yang ditargetkan pada suatu elemen HTML, maka declaration yang ditulis paling akhir akan lebih diprioritaskan. Mari kita lihat potongan kode berikut.
Property font-size
pada elemen p
akan bernilai 2rem
. Sedangkan property font-weight
akan bernilai 600
.
Selain itu, kita juga harus ingat bahwa style sheet yang ikut dalam proses cascading tidak hanya bersumber dari yang kita tulis sendiri. Setidaknya terdapat tiga jenis origin (asal) dari suatu style sheet, yaitu:
-
User-Agent Origin (Peramban)
Ini adalah style sheet yang berasal dari peramban dan ditargetkan ke elemen-elemen dasar HTML. Suatu peramban bisa memiliki rule bawaan yang berbeda dengan peramban lainnya. Kita bisa memanfaatkan pustaka seperti reset.css atau normalize.css untuk menyeragamkannya. Style sheet bawaan yang berasal dari peramban ini memiliki prioritas paling kecil.
-
User Origin (Pengguna)
Setiap pengguna bisa melakukan kustomisasi bawaan pada peramban yang mereka gunakan. Misalnya saja pengaturan ukuran dan jenis huruf pada Mozilla Firefox seperti yang ada pada tautan ini. Style sheet yang berasal dari pengaturan pengguna ini punya prioritas lebih tinggi dari user-agent origin.
-
Author Origin (Penulis)
Ini adalah style sheet yang punya prioritas paling tinggi di antara kedua jenis origin di atas. Style sheet ini berasal dari kode CSS yang kita, para pengembang web, tulis. Pustaka pihak ketiga yang kita gunakan termasuk dalam author origin. Declaration yang ditulis langsung (inline) pada atribut
style
di elemen HTML (misalnya:<div style="background: red;" />
) juga merupakan author origin.
Terdapat 2 jenis origin tambahan, yaitu animation origin dan transition origin. Keduanya berasal dari rule “virtual” yang merepresentasikan efek pada saat property transition
dan animation
berjalan. Transition origin punya prioritas lebih tinggi dari animation origin. Dan keduanya punya prioritas lebih tinggi dari ketiga jenis origin di atas.
Specificity
Dari aturan order dan origin yang sudah kita bahas di atas, kita tahu bahwa apabila suatu elemen memiliki beberapa declaration dari property yang sama, maka declaration yang ditulis paling akhir akan diprioritaskan dan diterapkan pada elemen tersebut. Namun, ternyata kita juga bisa menemukan kondisi dimana justru declaration yang ditulis lebih awallah yang diterapkan. Kondisi ini terjadi karena declaration tersebut memiliki specificity lebih tinggi dari yang lainnya. Specificity adalah bobot yang diberikan kepada setiap CSS declaration. Semakin tinggi bobotnya, maka akan semakin diprioritaskan.
Peramban menentukan specificity dengan cara melakukan kalkulasi bobot pada selector dari rule di mana CSS declaration itu dituliskan. Untuk mempermudah, kita bisa memberi bobot tertentu sesuai dengan jenis selector-nya.
-
ID Selector
Bobotnya 100. Misalnya
#login-form
dan#main
. -
Class Selector
Bobotnya 10. Misalnya
.blue
,.red
, dan.header
. -
Attribute Selector
Bobotnya 10. Misalnya
[type=checkbox]
dan[href*="kukuhsulistyo.com"]
. -
Pseudo Selector
Berbobot 10. Misalnya
:hover
,:first-child
, dan:nth-child(n)
. -
Type Selector
Bobotnya 1. Misalnya
h1
,p
, danform
. -
Pseudo-Element Selector
Bobotnya 1. Misalnya
::after
,::before
, dan::first-letter
. -
Universal selector
*
memiliki bobot 0. -
Combinator
Berbobot 0. Terdiri dari
+
,>
, dan~
. -
Negation
:not(...)
berbobot 0. Namun, selector di dalamnya tetap memiliki bobot.
Apabila sebuah rule memiliki lebih dari satu selector, maka bobotnya kita akumulasikan. Agar lebih jelas, kita coba lihat contohnya, Yuk!
Perhitungan: form
berbobot 1 dan #login
berbobot 100. Totalnya adalah 101.
Perhitungan: ul
berbobot 1, >
berbobot 0, li
berbobot 1, dan :first-child
berbobot 10. Jadi, totalnya adalah 12.
Perhitungan: a
berbobot 1, [href*='kukuhsulistyo.com']
berbobot 10, dan .primary
berbobot 10. Totalnya adalah 21.
Beberapa situs seperti specifishity.com dan cssspecificity.com memiliki contoh dan ilustrasi yang cukup lengkap mengenai specificity.
Penggunaan !important
Important declaration adalah CSS declaration yang memiliki kata kunci !important
di akhir penulisannya.
Kata kunci !important
akan membuat suatu declaration menjadi diprioritaskan dibanding dengan normal declaration (tanpa !important
). Aku biasa menggunakan teknik ini untuk meng-override styling dari pustaka pihak ketiga.
Penggunaan !important
juga akan berpengaruh pada mekanisme cascade yang sudah kita bahas sebelumnya.
-
Pengaruh Terhadap Order dan Origin
Berikut adalah aturan order dan origin yang terurut prioritasnya dari yang terkecil hingga terbesar apabila terdapat important declaration:
- User-Agent origin.
- User origin.
- Author origin.
- Animation origin.
- Author origin dengan
!important
. - User origin dengan
!important
. - User-Agent dengan
!important
. - Transition origin.
-
Pengaruh Terhadap Specificity
Important declaration akan memiliki bobot specificity yang paling besar dan akan lebih diprioritaskan dari pada selector lainnya. Untuk mempermudah pemahaman, kita bisa memberi bobot specificity 10.000 pada CSS declaration yang menggunakan
!important
.
Kita harus menggunaan important declaration dengan penuh kesadaran akan implikasinya terhadap cascade, karena bisa jadi justru akan mempersulit proses debugging dan overriding di masa depan. Sebisa mungkin manfaatkan sifat cascade untuk mengatur prioritas CSS declaration yang kita tulis.
Inheritance
Selain cascade, satu sifat penting lain dari CSS yang harus kita pahami adalah inheritance. Jika suatu property CSS pada elemen tidak mempunyai declaration yang secara eksplisit ditargetkan padanya, maka property tersebut akan memiliki nilai yang disesuaikan dengan nilai awalan (initial value)-nya. Misalnya saja property line-height
yang memiliki initial value normal
. Namun, ada beberapa property yang secara bawaan akan memiliki nilai yang disesuaikan dengan induknya. Kita menyebutnya sebagai inherited property. Jika teman-teman melihat bagian “Formal Definition” pada dokumentasi CSS di MDN, maka teman-teman akan menemukan keterangan “inherited” yang bernilai “yes” atau “no”. Misalnya saja pada dokumentasi property color
, diketahui kolom “inherited” bernilai “yes”. Artinya, property color
merupakan sebuah inherited property.
Selanjutnya, mari kita lihat potongan kode berikut.
Teks “Halo-halo Bandung” di dalam h1
akan berwarna lime
karena memang ada declaration yang secara eksplisit ditulis untuk mengaturnya. Tinjau bahwa tidak ada declaration yang secara langsung ditujukan untuk elemen p
, sehingga teks “Lagu ciptaan Ismail Marzuki” di dalam p
akan berwarna navy
. Hal ini terjadi karena property color
merupakan inherited property yang memiliki nilai bawaan dari induknya, yaitu header
. Namun, apa yang terjadi apabila header
tidak punya declaration untuk property color
? Hal yang akan terjadi adalah peramban akan mencari declaration untuk property color
ke induk-induk dari elemen header
secara rekursif hingga menemukannya.
Kita juga mengetahui bahwa property border
hanya akan diterapkan pada header
, tetapi tidak pada elemen-elemen di dalamnya. Hal tersebut dikarenakan property border
bukan merupakan inherited property. Namun, kita juga bisa “memaksa” suatu property agar menyesuaikan induknya dengan menggunakan inherit
sebagai nilainya.
Kesimpulan
Oke, Teman-teman. Kita sudah membahas sifat-sifat dasar dari CSS, yaitu cascade dan inheritance. Nah, selanjutnya mari kita bahas mengapa kasus pada kuis berakhir dengan keduanya berwarna biru.
- Kedua declaration merupakan author origin. Namun,
color: blue
memiliki prioritas lebih tinggi daripadacolor: red
karena ditulis paling akhir. - Kedua declaration memiliki bobot specificity yang sama yaitu 10, karena masing-masing memiliki sebuah class selector (
.red
dan.blue
). Specificity tidak mempengaruhi prioritas pada kasus ini. - Kedua declaration tidak menggunakan
!important
. - Sifat inheritance tidak berlaku karena nilai dari property
color
ditulis secara eksplisit. - Urutan penulisan pada atribut
class
di elemen HTML tidak mempengaruhi prioritas.
Jadi, property color
dari kedua elemen p
tersebut akan bernilai blue
.
Begitulah ceritaku mengenai sifat-sifat dasar CSS yang juga merupakan mekanisme penentuan nilai akhir dari suatu property CSS. Sifat-sifat CSS tersebut ada bukan untuk menyulitkan kita sebagai penggunanya, melainkan memudahkan kita dalam mengatur tampilan secara terstruktur, maintainable, dan scalable. Tentunya, kita harus memahami sifat-sifatnya terlebih dahulu agar bisa menggunakannya dengan tepat.
Oh iya, teman-teman juga bisa membaca spesifikasi lengkap CSS Cascade and Inheritance dari W3C di sini. Dan sebagai bahan bacaan lanjutan, ada beberapa pola desain CSS yang menurutku sangat mempertimbangkan sifat cascade dan inheritance seperti: BEM, ITCSS, SMACSS, dan CUBE.
Demikian, terima kasih telah mampir ke tulisanku ini. Semoga bermanfaat, Ya!