Tutorial CSS / Pewarisan, Spesifisitas, dan Kaskade CSS
Kaskade memilih di antara deklarasi CSS yang bersaing, sementara spesifisitas membandingkan kekuatan selektor dalam kondisi kaskade yang relevan. Pewarisan memberikan nilai tertentu dari induk ketika tidak ada deklarasi yang berlaku yang menentukan nilai tersebut; ini adalah mekanisme yang terkait tetapi berbeda.
Membedakan pewarisan dari deklarasi langsung
Pewarisan terjadi ketika elemen anak mewarisi nilai dari elemen induknya. Sementara properti yang terkait dengan warna teks dan font umumnya diwarisi, border dan padding tidak diwarisi secara default. Jika Anda mengasumsikan bahwa semua properti akan sama dengan induknya, Anda dapat keliru mengira bahwa border pada induk juga akan muncul pada setiap paragraf anak.
#main {
color: purple;
border: 1px solid purple;
}
p { color: #555; }
<main id="main">
<h1>Small Garden</h1>
<p>Visitor information.</p>
</main>
Dengan mengasumsikan kita hanya menerapkan kedua bagian ini, h1 akan mewarisi warna ungu dari induknya, main. Warna abu-abu yang Anda tentukan diterapkan pada p. Hanya karena #main induk adalah selektor ID, itu tidak mengalahkan penetapan langsung p sebagai anak. Ini karena bukan persaingan antara dua selektor yang diterapkan pada elemen yang sama. Border dibuat di sekitar kotak main dan tidak diduplikasi oleh border h1 dan p masing-masing.
Properti yang tidak diwariskan juga dapat mewarisi nilai yang dihitung dari induk dengan menyebutkannya sebagai border: inherit. Sebaliknya, bahkan jika ada deklarasi yang berlaku untuk elemen tersebut, meskipun itu adalah properti yang diwariskan, deklarasi itu diproses terlebih dahulu. Anda dapat mengetahui properti mana yang diwariskan dan apa arti mewarisi di deskripsi pewarisan CSS MDN.
Ikuti proses pengambilan keputusan kaskade
Mulailah dengan CSS penulis biasa, seperti aturan yang Anda tulis untuk halaman ini. Sebelum membandingkan deklarasi, verifikasi bahwa selektor cocok, sintaks valid, dan kondisi seperti media query berlaku. Kecualikan aturan yang tidak cocok dan deklarasi yang tidak valid dari perbandingan.
- Periksa kondisi teratas seperti asal gaya, tingkat kepentingan, dan lapisan. Asal gaya penulis, pengguna, dan gaya bawaan browser, apakah !important, apakah @layer digunakan, dll. relevan di sini. Jika kondisi teratas berbeda, keputusan tidak dibuat hanya dengan membandingkan skor selektor.
- Membandingkan kekhususan selektor dalam kondisi yang sama. Spesifisitas adalah kriteria untuk membandingkan seberapa spesifik sebuah selektor. Bandingkan ID, keluarga kelas, dan keluarga elemen dalam urutan itu.
- Jika prioritas sama, deklarasi yang ditulis terakhir yang digunakan. Dalam situasi di mana tidak ada kondisi tambahan seperti @scope, seperti pada contoh dalam pelajaran ini, seri akhir diselesaikan berdasarkan urutan sumber.
- Untuk setiap properti, CSS menyelesaikan deklarasi yang berlaku dan kemudian melakukan pengaturan default jika diperlukan. Properti yang dapat diwariskan dapat memperoleh nilai dari induk; properti lain biasanya menggunakan nilai awalnya. Ini tidak berarti bahwa setiap deklarasi dalam aturan yang menang menggantikan seluruh aturan sebelumnya.
Kaskade adalah proses penyelesaian konflik CSS secara lengkap; spesifisitas selektor adalah salah satu kriterianya. Animasi, transisi, lapisan, dan ruang lingkup memperkenalkan aturan tambahan, jadi contoh sederhana di sini tidak mewakili setiap kasus. Aturan pengurutan kaskade W3C mendefinisikan hubungan antara asal, kepentingan, dan lapisan. Contoh lengkap di bawah ini tidak menggunakan animasi, transisi, @layer, atau @scope. Mengatur CSS dengan Gaya Bersama, Nesting, dan Lapisan menunjukkan pengelompokan aturan ke dalam lapisan.
Bandingkan spesifisitas dalam tiga kolom
Selektor dasar dalam pelajaran ini dapat dibaca dalam tiga kolom: jumlah ID, jumlah kelas/atribut/kelas semu, dan jumlah elemen/elemen semu. Bandingkan dari kolom kiri, dan jika ada perbedaan, putuskan berdasarkan hasilnya. Jangan hanya menghafalnya sebagai tabel skor desimal dengan menambahkan ID=100, kelas=10, elemen=1. Hanya karena ada banyak kelas tidak berarti itu melampaui kolom ID.
| selektor | ID | Kelas, atribut, kelas semu | Elemen/Elemen semu | notasi |
|---|---|---|---|---|
p |
0 | 0 | 1 | 0-0-1 |
.notice |
0 | 1 | 0 | 0-1-0 |
p.notice |
0 | 1 | 1 | 0-1-1 |
[required] |
0 | 1 | 0 | 0-1-0 |
a:hover |
0 | 1 | 1 | 0-1-1 |
p::before |
0 | 0 | 2 | 0-0-2 |
#opening |
1 | 0 | 0 | 1-0-0 |
#main .notice |
1 | 1 | 0 | 1-1-0 |
p.notice dan .notice memiliki kolom ID yang sama dan kolom kelas yang sama. Ada perbedaan antara 1 dan 0 di kolom elemen, jadi p.notice tinggi. #opening dan p.notice memiliki perbedaan 1 dan 0 di kolom pertama, jadi #opening tinggi. Spasi putih, notasi relasional seperti >, +, ~ dan selektor universal * tidak secara langsung meningkatkan jumlah perbandingan ini.
p.notice { color: #087f5b; }
.notice { color: tomato; }
Di bawah kondisi asal, kepentingan, dan lapisan yang sama, p.notice memiliki spesifisitas lebih tinggi daripada .notice, jadi warna hijaunya menang bahkan ketika muncul lebih awal. Selektor yang identik memiliki spesifisitas yang sama, memungkinkan urutan sumber menyelesaikan seri. Beberapa kelas semu fungsional memiliki aturan spesifisitas tambahan. Lihat MDN: Spesifisitas.
Selesaikan setiap properti secara terpisah
.notice {
color: blue;
padding: 12px;
border: 1px solid #087f5b;
}
.notice {
color: tomato;
padding: 20px;
}
Jika hanya dua aturan ini yang diterapkan pada elemen yang sama, warna dan padding menggunakan deklarasi dari aturan terakhir, dan border dari aturan sebelumnya tetap ada. Hanya karena tidak ada border di aturan berikutnya tidak berarti seluruh aturan sebelumnya hilang. CSS harus dipahami sebagai “menentukan nilai untuk setiap properti” daripada “memilih seluruh blok aturan”.
Sebagai contoh, warna teks mungkin berasal dari aturan ID, margin mungkin berasal dari aturan kelas yang lebih baru, dan border mungkin berasal dari aturan kelas sebelumnya. Bahkan ketika Anda melihat coretan di alat pengembang, bacalah deklarasi satu per satu. Hanya karena warna memiliki coretan tidak berarti padding dari blok yang sama tidak diterapkan.
Perkirakan contoh lengkap sebelum menjalankannya
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Small Garden</title>
<style>
body { margin: 24px; font-family: sans-serif; line-height: 1.7; }
#main { color: purple; }
p { color: #555; }
.notice {
color: blue;
padding: 12px;
border: 1px solid #087f5b;
}
p.notice { color: #087f5b; }
.notice { color: tomato; padding: 20px; }
#opening { color: #1d4ed8; }
</style>
</head>
<body>
<main id="main">
<h1>Small Garden</h1>
<p id="opening" class="notice">A: We open at 9am every day.</p>
<p class="notice">B: Prepare a water bottle and comfortable shoes.</p>
<p>C: Please inquire at the information desk.</p>
</main>
</body>
</html>
Perkirakan warna A·B·C dan padding notice sebelum membukanya di peramban Anda. Jika Anda menyimpan seluruh kode sebagai index.html dan membukanya, Anda akan mendapatkan hasil berikut. Font dan tinggi baris pada body adalah pengaturan tambahan untuk memudahkan melihat.
| objek dan properti | hasil akhir | Alasan keputusan |
|---|---|---|
| warna h1 | Ungu | Mewarisi warna dari main. Tidak ada deklarasi warna lain di h1. |
| warna A | Biru #1d4ed8 | #opening memiliki spesifisitas lebih tinggi daripada p.notice, .notice, p yang diterapkan pada A yang sama. |
| warna B | Hijau #087f5b | p.notice memiliki spesifisitas lebih tinggi daripada .notice yang muncul kemudian. |
| warna C | Abu-abu #555 | Menggunakan nilai langsung untuk p dan tidak mewarisi warna ungu dari induk. |
| padding dari A·B | 20px | Dua deklarasi .notice memiliki spesifisitas yang sama, sehingga padding pada deklarasi yang terakhir menang. |
| border dari A·B | garis solid hijau 1px | Karena tidak ada deklarasi border pada aturan yang terakhir, deklarasi valid sebelumnya tetap berlaku. |
Saat diperiksa di Computed, warna A dapat ditampilkan sebagai rgb(29, 78, 216), warna B dapat ditampilkan sebagai rgb(8, 127, 91), dan warna C dapat ditampilkan sebagai rgb(85, 85, 85). Meskipun notasi warnanya berbeda, ini menunjukkan nilai yang sama. Periksa bahwa padding adalah 20px di setiap arah dan ketebalan maupun bentuk garis border sama.
Bandingkan !important dan gaya inline
!important adalah notasi yang mengubah pentingnya sebuah deklarasi. Ini bukan fungsi yang menambahkan angka besar ke tiga kolom dari selektor. Dari sumber yang sama penulisnya, deklarasi penting memiliki prioritas atas deklarasi biasa, jadi menambahkan aturan di bawah ini di akhir seluruh contoh akan mengubah warna A dan B menjadi tomato. Deklarasi warna biasa di ID juga tidak lebih diutamakan dibandingkan deklarasi penting ini.
.notice { color: tomato !important; }
Hasil ini tidak berarti bahwa penting selalu lebih kuat daripada semua gaya. Deklarasi !important milik pengguna dan nilai selama transisi mengikuti urutan prioritas tersendiri. Bahkan di antara deklarasi penting, Anda harus terlebih dahulu memeriksa sumber dan lapisan. Dalam latihan ini, amati efek !important, lalu hapus aturan yang Anda tambahkan. Biasanya, untuk pemeliharaan lebih baik mengatur rentang pilihan dan struktur terlebih dahulu.
<p class="notice" style="color: purple;">B: Information on what to prepare</p>
Dalam contoh asli di mana aturan penting dihapus, jika Anda menambahkan warna inline di B seperti di atas, itu akan memiliki prioritas dibandingkan aturan lembar gaya reguler dan B akan menjadi ungu. Gaya inline diperlakukan secara terpisah dari tiga kolom selektor default dalam tabel di atas. Sekali lagi, menambahkan important dalam aturan kelas umum memungkinkan aturan itu memiliki prioritas dibandingkan warna inline reguler. Oleh karena itu, “jika itu inline, itu secara mutlak adalah yang terkuat” juga merupakan penjelasan tanpa syarat.
Latihan untuk mendiagnosis konflik
- Dalam contoh penuh asli, pindahkan aturan
p.noticeke bagian bawah. Pastikan B tetap hijau dan A mempertahankan warna biru dari ID-nya. Dalam kondisi dengan spesifisitas tinggi, aturan tersebut tidak akan dibatalkan hanya dengan mengubah urutannya. - Selanjutnya, ubah hanya selektor p.notice menjadi
.noticedan tempatkan di bagian bawah. Warna dari B menggunakan hijau yang ditentukan oleh .notice terakhir. Karena kita memiliki selektor yang sama, urutan sekarang menjadi kriteria keputusan. Setelah konfirmasi, kembalikan ke aslinya. - Hapus hanya atribut
id="opening"dari A. Lihat apakah A menjadi hijau yang sama dengan B. Meskipun ID pada induk main tetap sama, itu tidak mengalahkan warna hijau yang diberikan langsung ke A. Setelah konfirmasi, kembalikan atribut ID tersebut. - Dalam langkah terpisah, terapkan contoh !important dan gaya inline di atas satu per satu dan bandingkan. Alih-alih meninggalkan aturan praktik sebelumnya, kembali ke aslinya dan uji satu kondisi berikutnya pada satu waktu.
Jika hasilnya berbeda dari yang Anda harapkan, Periksa CSS dengan DevTools: Styles dan Computed. Pilih elemen yang benar, temukan deklarasi untuk properti tersebut, bandingkan tingkat kepentingannya, selektor, dan urutannya, lalu periksa nilai akhirnya. Menambahkan ID atau !important tanpa menemukan penyebabnya dapat mengubah warna sekarang sambil membuat pengeditan di masa depan menjadi lebih sulit.




