Mengganti variabel CSS pada elemen anak tidak menyusun ulang properti kustom gabungan yang diwarisi dari induknya. Induk sudah menyelesaikan referensi bertingkat tersebut. Agar nilai milik anak digunakan, deklarasikan properti gabungan pada anak itu atau susun properti akhirnya di sana.
Panduan ini menjelaskan perilaku tersebut dan memberikan latihan desktop yang dapat direproduksi di Chrome pada Mac. Tujuannya adalah membuat border komponen mengikuti penggantian warna lokalnya sambil mempertahankan nilai bawaan bersama.
Mengapa komposit yang diwarisi tetap menggunakan warna induk?
Perhatikan fragmen CSS ini. Fragmen ini mengasumsikan elemen .sample-tile berada di dalam elemen .sample-board:
.sample-board {
--sample-color: teal;
--sample-border: 6px solid var(--sample-color);
}
.sample-tile {
--sample-color: darkorange;
border: var(--sample-border);
}
Border anak tetap berwarna teal. Spesifikasi CSS Variables menyatakan bahwa properti kustom menyelesaikan fungsi var() bertingkatnya pada saat nilai terhitung, sebelum pewarisan. Akibatnya, anak mewarisi komposit yang setara dengan 6px solid teal; anak tidak mewarisi ekspresi yang akan mengganti --sample-color dengan nilai milik anak. CSS Custom Properties for Cascading Variables Module Level 1.
Di sini terdapat dua properti terpisah. Menetapkan --sample-color pada anak mengubah nilai lokal properti tersebut. Itu tidak sekaligus mendeklarasikan nilai baru untuk --sample-border. Referensi properti kustom MDN menjelaskan bahwa properti kustom biasa yang tidak terdaftar diwariskan, dengan nilai terhitung yang variabelnya sudah diganti. Custom properties: CSS variables.
Urutan dalam contoh ini adalah:
- Induk menghitung
--sample-colorsebagaiteal. - Nilai tersebut menggantikan variabel pada
--sample-border, sehingga menghasilkan6px solid teal. - Anak mewarisi komposit itu dan secara terpisah menetapkan token warnanya sendiri menjadi
darkorange. - Deklarasi
borderpada anak menggunakan komposit teal yang diwarisi.
Ini bukan cuplikan nilai induk yang permanen. Jika warna induk berubah, kompositnya dapat diperbarui lalu diwariskan kembali. Batasnya adalah elemen tempat referensi bertingkat diselesaikan: penggantian pada turunan tidak menjangkau ke atas untuk mengubah perhitungan itu. CSS Variables: resolving dependencies.
Reproduksi perilaku ini di Chrome pada Mac
Gunakan halaman kosong agar gaya halaman yang sudah ada tidak mengganggu. Buka tab Chrome baru, masukkan about:blank di bilah alamat, lalu tekan Command + Option + J untuk membuka Console. Google mendokumentasikan pintasan Mac ini dalam panduan DevTools-nya. Open Chrome DevTools.
Program konsol browser lengkap berikut membuat tiga bentuk abstrak berlabel beserta stylesheet-nya. Program ini tidak memerlukan pustaka, gambar, permintaan jaringan, atau elemen halaman yang sudah ada. Jalankan seluruh blok sekali pada halaman kosong. Hasil yang diharapkan di bawah diturunkan dari aturan CSS yang terdokumentasi; hasil tersebut tidak disajikan sebagai pengukuran browser yang direkam.
(() => {
const board = document.createElement("section");
board.className = "sample-board";
const style = document.createElement("style");
style.textContent = `
.sample-board {
--sample-color: teal;
--sample-border: 6px solid var(--sample-color);
display: flex;
flex-wrap: wrap;
gap: 24px;
padding: 32px;
font: 16px system-ui;
}
.sample-board .sample-tile {
--sample-color: darkorange;
display: grid;
place-items: center;
width: 120px;
height: 80px;
border: var(--sample-border);
border-radius: 24px;
background: white;
color: black;
}
.sample-board .sample-local {
--sample-border: 6px solid var(--sample-color);
}
.sample-board .sample-direct {
border: 6px solid var(--sample-color);
}
`;
const samples = [
["Inherited", "sample-inherited"],
["Local", "sample-local"],
["Direct", "sample-direct"]
];
const tiles = samples.map(([label, className]) => {
const tile = document.createElement("div");
tile.className = `sample-tile ${className}`;
tile.textContent = label;
board.append(tile);
return tile;
});
document.head.append(style);
document.body.append(board);
function report(stage) {
console.log(stage);
console.table(tiles.map((tile) => {
const computed = getComputedStyle(tile);
return {
sample: tile.textContent,
localColor: computed
.getPropertyValue("--sample-color").trim(),
composite: computed
.getPropertyValue("--sample-border").trim(),
paintedBorder: computed.borderTopColor
};
}));
}
report("Initial values");
board.style.setProperty("--sample-color", "rebeccapurple");
report("After changing the parent color");
})();
Program ini mencetak dua tabel. Warna border yang diharapkan adalah:
| Contoh | Awalnya | Setelah induk berubah | Alasan |
|---|---|---|---|
Inherited |
Teal | Ungu | Menggunakan komposit terhitung milik induk |
Local |
Oranye | Oranye | Mendeklarasikan komposit pada anak |
Direct |
Oranye | Oranye | Mengganti variabel dengan warna lokal secara langsung di border |
Ketiga anak mempertahankan darkorange sebagai token warna lokalnya. Petunjuk diagnostik yang berguna adalah contoh Direct: komposit yang diwarisinya tetap memuat warna induk, tetapi border yang ditampilkan menggunakan token lokal karena deklarasi border tersebut tidak memakai komposit itu.
getComputedStyle() membaca nilai properti yang sudah diselesaikan setelah stylesheet aktif diterapkan. Dengan demikian, alat ini dapat mengungkap nilai yang benar-benar diterima elemen, alih-alih sekadar menampilkan ekspresi yang ditulis. Serialisasi warna mungkin muncul sebagai nilai rgb(), bukan nama warna aslinya. Window: getComputedStyle() method.
Muat ulang tab kosong untuk menghapus latihan. Untuk halaman yang ditulis sendiri, masukkan perbaikan CSS yang dipilih ke stylesheet-nya; perubahan di konsol berguna untuk diagnosis, tetapi tidak mengedit berkas sumber Anda.
Perbaikan mana yang sebaiknya dipilih?
Deklarasikan komposit pada batas komponen
Contoh Local mempertahankan token border yang dapat digunakan ulang dan mendeklarasikan resepnya pada elemen yang sama dengan tempat penggantian nilainya diberikan. Berikut fragmen CSS yang relevan dari program tersebut:
.sample-board .sample-local {
--sample-color: darkorange;
--sample-border: 6px solid var(--sample-color);
border: var(--sample-border);
}
Pilih pola ini ketika beberapa deklarasi memerlukan nilai susunan yang sama. Tempatkan nilai bawaan primitif pada leluhur dan deklarasi komposit pada komponen yang memiliki penyesuaian tersebut. Properti kustom dapat dideklarasikan pada elemen tertentu dan diwariskan ke turunannya; properti itu tidak harus berada di :root. Using CSS custom properties.
Penempatannya tetap penting lebih jauh di dalam pohon elemen. Jika cucu mengganti primitif lagi, komposit warisan dari komponen ini tetap mencerminkan perhitungan komponen tersebut. Deklarasikan resep itu kembali pada batas turunan mana pun yang perlu menyusun hasil berbeda.
Susun properti akhir di tempat properti itu digunakan
Contoh Direct menghapus token perantara dari deklarasi border. Aturan inti fragmen CSS-nya adalah:
.sample-board .sample-direct {
--sample-color: darkorange;
border: 6px solid var(--sample-color);
}
Pilih cara ini ketika hanya satu deklarasi yang memerlukan kombinasi tersebut. Anda tetap dapat menggunakan token lebar, gaya, dan warna secara terpisah, lalu menggabungkannya dalam deklarasi border komponen. MDN mendokumentasikan bahwa var() dapat mengganti seluruh atau sebagian nilai properti lain. Using CSS custom properties.
Ganti seluruh komposit jika komposit itu merupakan kontrol publik
Terkadang penyesuaian yang dimaksudkan untuk komponen adalah keseluruhan border. Dalam hal itu, berikan pengganti lokal untuk --sample-border, misalnya 6px solid darkorange, alih-alih hanya mengubah input yang sebelumnya digunakan.
Gunakan panduan keputusan ini saat memilih kontrak komponen:
| Penyesuaian yang diinginkan | Pola yang sesuai |
|---|---|
| Satu warna lokal mengontrol satu border | Susun langsung di border |
| Beberapa deklarasi menggunakan nilai susunan yang sama | Deklarasikan komposit pada komponen |
| Pemanggil memberikan seluruh border | Ganti komposit itu sendiri |
| Turunan harus menggunakan nilai susunan induk secara persis | Pertahankan komposit yang diwarisi |
Mengapa spesifisitas, nilai cadangan, atau kata kunci pewarisan tidak menyusunnya ulang?
Pertama, pastikan apakah penggantian primitif benar-benar berlaku. Jika --sample-color yang telah diselesaikan pada anak sudah bernilai darkorange, membuat deklarasi yang sama lebih spesifik tidak akan mengubah --sample-border terpisah yang diwarisi. Kedua properti itu sudah memiliki nilai; masalahnya terletak pada tempat komposit disusun.
Demikian pula, --sample-border: inherit mengambil nilai terhitung milik induk. Pewarisan biasa meneruskan nilai terhitung, alih-alih menjalankan ulang deklarasi yang ditulis pada induk dalam konteks anak. Inheritance.
Nilai cadangan seperti var(--sample-border, 6px solid darkorange) juga membiarkan border teal warisan yang valid tetap utuh. Nilai cadangan var() menangani properti kustom yang tidak memiliki nilai yang dapat digunakan; nilai itu tidak membandingkan nilai tersebut dengan input pilihan turunan. var() CSS function.
Pisahkan nilai tidak valid dari masalah pewarisan ini. Misalnya, token tak terdaftar yang berisi 12px dapat menjadi nilai properti kustom, tetapi menghasilkan nilai tidak valid saat diganti ke dalam border-color. Nilai cadangan di dalam pemanggilan var() itu bukan alternatif untuk pemeriksaan tipe secara umum. MDN menjelaskan mengapa penggantian properti kustom dapat menghasilkan deklarasi yang menjadi tidak valid pada saat nilai terhitung. Using CSS custom properties.
Apakah mendaftarkan variabel dengan @property akan memperbaikinya?
@property memungkinkan Anda menentukan sintaks, nilai awal, dan perilaku pewarisan suatu properti kustom. Fitur ini tidak membuat komposit warisan milik induk dievaluasi ulang berdasarkan input yang diganti pada anak. Mendaftarkan primitif dengan inherits: false akan mengubah cara primitif itu diperoleh, sedangkan mendaftarkan komposit dengan cara tersebut akan menghentikan pewarisan normalnya. Keduanya tidak menyediakan resep lokal yang belum ada. @property CSS at-rule.
Pendaftaran juga memiliki batas kompatibilitas yang berbeda. MDN menandai properti kustom biasa sebagai tersedia luas di berbagai browser sejak April 2017, sedangkan @property mencapai ketersediaan Baseline pada Juli 2024 dan mungkin tidak tersedia di browser lama. Kedua perbaikan yang ditunjukkan tidak memerlukan pendaftaran. Custom properties: CSS variables, @property CSS at-rule.
Cara mendiagnosis masalah yang sama di stylesheet Anda
Gunakan perbandingan tiga kolom dari latihan pada elemen yang tampilannya bermasalah:
- Baca token primitif, seperti
--sample-color. - Baca token komposit, seperti
--sample-border. - Baca properti yang ditampilkan, seperti
border-top-color. - Temukan elemen tempat deklarasi komposit berlaku.
- Pindahkan atau ulangi deklarasi tersebut pada batas penyesuaian yang dimaksud, atau susun langsung di properti akhir.
Untuk menemukan aturan terkait di Chrome, klik kanan bentuk tersebut dan pilih Inspect. DevTools memilih elemennya di Elements, dan tab Styles menampilkan aturan CSS yang diterapkan. Open Chrome DevTools.
Jika primitif menunjukkan nilai lokal yang diinginkan, tetapi komposit masih memuat nilai leluhur, periksa terlebih dahulu lokasi deklarasi komposit. Definisikan resep di tempat inputnya seharusnya dibaca, lalu verifikasi token yang telah diselesaikan dan hasil yang ditampilkan. Dengan begitu, komponen memiliki batas penyesuaian yang jelas dan dapat diprediksi.
Sumber
- CSS Custom Properties for Cascading Variables Module Level 1 — W3C.
- Custom properties (--*): CSS variables — MDN Web Docs.
- Using CSS custom properties (variables) — MDN Web Docs.
- Inheritance — MDN Web Docs.
- var() CSS function — MDN Web Docs.
- @property CSS at-rule — MDN Web Docs.
- Window: getComputedStyle() method — MDN Web Docs.
- Open Chrome DevTools — Chrome for Developers.