Tutorial CSS / Variabel CSS: var(), Lingkup, Pewarisan, dan Fallback

Properti kustom CSS menyimpan nilai yang dapat digunakan ulang dan dirujuk dengan var() dalam nilai properti. Ruang lingkupnya mengikuti kaskade dan pewarisan, dan fallback (nilai pengganti) pada var() tidak otomatis menggantikan nilai variabel yang sudah didefinisikan tetapi tidak cocok untuk properti penerima.

Pilih variabel bersama yang bermakna

Jika Anda menggunakan warna aksen yang sama untuk beberapa tombol dan kartu, Anda dapat mengelompokkannya ke dalam variabel yang bermakna daripada menyalin kode warna ke setiap selector. Saat mengubah warna aksen, jika Anda memodifikasi sebuah deklarasi, tempat yang merujuk nilai tersebut juga akan berubah. Jika Anda membuat variabel, bahkan nilai yang hanya digunakan di satu tempat dan tidak memiliki peran terpisah, beban untuk melacak nama sebenarnya dapat meningkat.

:root {
  --accent: #1d5f91;
  --space-unit: .5rem;
}
.button { color: white; background: var(--accent); }
.card { border: 2px solid var(--accent); padding: calc(var(--space-unit) * 3); }

Hanya mendeklarasikan warna dalam kode di atas tidak mengubah layar. Nilai tersebut perlu digunakan melalui var() pada properti nyata, misalnya background atau border. Jika nama menunjukkan peran, seperti --accent, alih-alih menyebut warna saat ini, seperti --blue, akan lebih sedikit membingungkan saat mengganti ke warna lain nanti. --accent dan --Accent adalah nama yang berbeda, jadi cocokkan huruf besar/kecil dan ejaannya.

var() digunakan untuk nilai properti seperti color atau padding. Selector atau nama properti tidak bisa diganti dengan variabel, dan breakpoint tidak dapat ditentukan dengan menaruh @media (min-width: ...) atau var() dalam nilai kondisi dari query ukuran container. Tulis breakpoint langsung di pernyataan kondisional yang sesuai, dan bedakan dari nilai yang dapat diterapkan variabel, seperti warna atau jarak elemen.

Pahami root, inheritance, dan lingkup komponen

Dalam dokumen HTML, :root mencocokkan elemen HTML tingkat atas, jadi sangat berguna untuk memiliki nilai default umum dalam dokumen. Properti kustom berawalan -- yang tidak didaftarkan dengan @property diwariskan ke elemen turunan. Pendaftaran @property dapat menentukan aturan pewarisan yang berbeda. Nilai yang dideklarasikan dalam sebuah kartu dapat digunakan oleh keturunan, seperti judul, tetapi tidak diteruskan ke kartu saudara yang tidak terkait.

.card { --card-accent: var(--accent); }
.card.warning { --card-accent: #a63e32; }
.card { border-color: var(--card-accent); }
.card h2 { color: var(--card-accent); }

Aturan ini adalah bagian komponen dari contoh lengkap di bawah ini. .card.warning mencocokkan kartu dengan kedua kelas. Menang atau kalah tidak ditentukan oleh urutan daftar kelas HTML, tetapi menurut aturan Pewarisan, Spesifisitas, dan Kaskade CSS untuk menentukan nilainya. Mengubah aksen global akan mengubah kartu default, dan kartu peringatan dengan card-accent mereka sendiri akan mempertahankan warna peringatan aslinya.

Ketika menggabungkan variabel dengan variabel lain, juga penting elemen mana nilai itu dihitung. Jika --line-color: var(--accent) dihitung di induk kemudian diteruskan ke anak, nilai --line-color yang sudah diwariskan tidak selalu akan dihitung ulang hanya karena aksen ditimpa di anak. Nilai turunan yang seharusnya mengikuti aksen keturunannya jelas lebih baik dideklarasikan di elemen atau langsung merujuk aksen pada nilai properti yang menggunakannya. Untuk definisi cakupan dan pewarisan, lihat spesifikasi properti khusus CSS.

Membedakan nilai fallback dan nilai komputasi yang tidak valid

var(--notice-color, #6a3989) menyediakan nilai fallback ungu ketika nilai variabel hilang dan tidak dapat digunakan. Bahkan jika variabel didefinisikan dan memiliki nilai yang berarti di properti lain, seperti 20px, jika nilai tersebut tidak sesuai dengan warna, deklarasi warna menjadi tidak valid pada saat perhitungan. Dalam kasus ini, Anda tidak boleh mengharapkan untuk “digantikan oleh ungu”.

status variabel Hasil deklarasi warna Warna untuk seluruh contoh
--notice-color belum didefinisikan Menggunakan nilai fallback untuk var ungu
--notice-color bernilai warna merah Gunakan nilai yang telah didefinisikan merah
--notice-color bernilai 20px Aturan pewarisan/nilai awal diterapkan karena tidak cocok dengan warna Karena warna diwariskan, gunakan warna teks hijau dari induk.

Seperti yang ditunjukkan di bawah, meskipun ada deklarasi biru terlebih dahulu dalam aturan yang sama, jika nilai setelah substitusi variabel dalam deklarasi kedua tidak cocok, itu tidak akan kembali ke biru pertama. Setelah deklarasi yang dipilih dalam cascade tidak berlaku pada saat evaluasi, aturan pewarisan warna diterapkan. Dalam situasi yang sama, properti yang tidak diwariskan dapat diperlakukan sebagai nilai awal properti tersebut. MDN Panduan Properti Kustom menjelaskan perbedaan antara nilai pengganti dan nilai tidak sah.

.sample {
  color: #1d5f91;
  color: var(--notice-color, #6a3989);
}
.sample.bad { --notice-color: 20px; }

Anda juga dapat menempatkan variabel lain dalam nilai fallback. Sebagai contoh, var(--button-accent, var(--accent, #1d5f91)) mencari nilai yang akan digunakan, dimulai dengan nilai khusus tombol, kemudian nilai umum, dan akhirnya warna utama. Namun, jika penggunaan angka, panjang, dan warna dicampur, masalah yang sama terjadi, jadi nama variabel dan penggunaannya harus dikelola bersama.

Gabungkan nilai dan satuan dengan calc()

Contohnya mengalikan --space-unit: .5rem dengan 3 untuk mengatur padding kartu. rem menggunakan ukuran font root, jadi mengubah ukuran tersebut mengubah jarak. Gunakan calc() untuk perhitungan daripada menggabungkan string, dan beri spasi di sekitar operator penjumlahan dan pengurangan. Untuk detail lebih lanjut, lihat Warna dan Satuan CSS: px, em, rem, dan Persentase.

:root {
  --space-unit: .5rem;
  --space-card: calc(var(--space-unit) * 3);
}
.card { padding: var(--space-card); }

Konsistenlah dalam memilih apakah variabel menyertakan satuan atau hanya angka. Jika Anda memasukkan nilai tanpa satuan seperti 2 pada variabel panjang, mungkin tidak cocok untuk aplikasi yang memerlukan satuan. Hindari kombinasi penggunaan yang berbeda, seperti menerapkan calc pada variabel yang berisi warna. Untuk sintaks dasar dari formula, lihat dokumen MDN calc.

Jalankan perbandingan lingkup dan cadangan

Simpan kode berikut sebagai custom-properties.html dalam UTF-8 dan buka di peramban Anda. Bandingkan warna aksen dari kedua kartu dan warna teks dari tiga kalimat. Makna dari warna juga ditulis dalam huruf agar pembaca tidak harus mengandalkan warna saja untuk membedakan hasil.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>CSS variable scope and substitution values</title>
  <style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; padding: 1rem; color: #183044; font-family: sans-serif; line-height: 1.6; }
main { max-width: 46rem; margin-inline: auto; }
h1 { font-size: 1.5rem; } h2 { font-size: 1.2rem; }
button, input { font: inherit; }
button { cursor: pointer; }
:focus-visible { outline: 3px solid #164f73; outline-offset: 3px; }
:root { --space-unit: .5rem; --space-card: calc(var(--space-unit) * 3); --accent: #1d5f91; }
.cards { display: grid; gap: 1rem; }
.card { --card-accent: var(--accent); padding: var(--space-card); border: 2px solid var(--card-accent);
  border-radius: .5rem; background: #f6f9fb; }
.card h2 { color: var(--card-accent); margin-block: 0 .5rem; }
.card p { margin: 0; }
.card.warning { --card-accent: #a63e32; }
.fallback-area { margin-block: 2rem; padding: 1rem; border: 1px solid #8a9ba7; color: #28633b; }
.sample { color: #1d5f91; color: var(--notice-color, #6a3989); }
.sample.bad { --notice-color: 20px; }
.sample.good { --notice-color: #a63e32; }
  </style>
</head>
<body>
<main>
<h1>Variable scope and fallbacks</h1>
<div class="cards">
  <article class="card"><h2>Basic card</h2><p>The heading and border share the same accent color.</p></article>
  <article class="card warning"><h2>warning card</h2><p>The accent color changes only inside this card.</p></article>
</div>
<section class="fallback-area">
  <h2>The parent's text color is green</h2>
  <p class="sample missing">Undefined: purple fallback</p>
  <p class="sample bad">20px: Doesn't match the color, so it inherits the green color from the parent.</p>
  <p class="sample good">Defined as red: use that color</p>
</section>
</main>
</body>
</html>
  1. Pastikan bahwa judul dan bingkai kartu dasar berwarna biru dan kartu peringatan berwarna merah. Tiga kalimat di bawah ini masing-masing berwarna ungu, hijau, dan merah.
  2. Ubah hanya aksen root menjadi #28633b. Judul dan bingkai kartu default harus berubah, sementara kartu peringatan mempertahankan warna peringatannya sendiri. Kembalikan aksen root ke #1d5f91 setelah pengecekan.
  3. Ganti hanya --space-unit dengan 1rem. Padding kedua kartu akan meregang bersama. Setelah konfirmasi, kembalikan menjadi .5rem.
  4. Ubah hanya --notice-color pada .sample.bad dari 20px ke #1d5f91. Kalimat akan berubah dari hijau menjadi biru. Setelah konfirmasi, kembalikan menjadi 20px.
  5. Hapus hanya deklarasi --notice-color pada .sample.bad. Kali ini fallback ungu digunakan. Bandingkan dengan hasil biru dari langkah sebelumnya dan kembalikan deklarasi aslinya.

Diagnosa variabel yang hilang atau salah

  • Di alat pengembang, periksa apakah nama variabel dan nilai benar-benar ada di elemen itu. Periksa ejaan, kapitalisasi, dan cakupan deklarasi terlebih dahulu.
  • Periksa apakah keturunan atau aturan lain menimpa variabel yang sama. Tidak selalu menjadi kesalahan jika suatu komponen mempertahankan nilainya sendiri meskipun nilai umum berubah.
  • Periksa apakah variabel tersebut direferensikan pada properti yang sebenarnya dan apakah satuan dan jenis nilai pengganti sudah benar.
  • Jika sebuah nilai dibuat melalui beberapa variabel, periksa elemen yang dihitung dan nilai yang diwarisi. Juga hindari deklarasi yang merujuk pada variabel yang sama dengan dirinya sendiri atau yang merujuk secara sirkular.

Anda dapat memanfaatkan variabel dengan membedakan antara warna umum dan jarak dalam desain serta pengecualian untuk setiap komponen, dan memeriksa hasilnya sebelum dan sesudah perubahan. Daripada menambah jumlah nama variabel, menjelaskan nilai mana yang dibagikan di ruang lingkup mana lebih berguna untuk pemeliharaan.