Lapisan kaskade (aturan CSS @layer
) akan hadir di Chromium 99, Firefox 97, dan Safari 15.4 Beta. Alat ini memungkinkan kontrol yang lebih eksplisit terhadap file CSS Anda untuk mencegah konflik kekhususan gaya. Hal ini sangat berguna untuk codebase besar, sistem desain, dan saat mengelola gaya pihak ketiga dalam aplikasi.
Menambahkan lapisan CSS dengan cara yang jelas akan mencegah penggantian gaya yang tidak terduga dan mendorong arsitektur CSS yang lebih baik.
Spesifisitas CSS dan kaskade
Kekhususan CSS adalah cara CSS menentukan gaya yang akan diterapkan ke elemen mana. Berbagai pemilih yang dapat Anda gunakan menentukan kekhususan aturan gaya apa pun. Misalnya, elemen kurang spesifik daripada class atau atribut, yang pada gilirannya kurang spesifik daripada ID. Ini adalah bagian dasar dari mempelajari CSS.
Orang-orang beralih ke konvensi penamaan CSS seperti BEM untuk mencegah penggantian kekhususan secara tidak sengaja. Dengan memberikan satu nama class ke semuanya, semuanya akan ditempatkan pada bidang spesifitas yang sama. Namun, mempertahankan gaya yang teratur seperti itu tidak selalu memungkinkan, terutama saat menggunakan kode dan sistem desain pihak ketiga.
Lapisan cascade bertujuan untuk mengatasi masalah ini. Keduanya memperkenalkan lapisan baru ke cascade CSS. Dengan gaya berlapis, prioritas lapisan selalu mengalahkan kekhususan pemilih.
Misalnya, pemilih .post a.link
memiliki spesifitas yang lebih tinggi daripada .card a
. Jika mencoba menata gaya link, di dalam kartu, dalam postingan, Anda akan mendapati bahwa pemilih yang lebih spesifik akan diterapkan.
Dengan menggunakan @layer
, Anda dapat lebih eksplisit tentang kekhususan gaya masing-masing, dan memastikan gaya link kartu Anda mengganti gaya link postingan, meskipun secara numerik kekhususannya mungkin lebih rendah jika semua CSS Anda berada di bidang yang sama. Hal ini karena prioritas cascade. Gaya berlapis membuat "bidang" kaskade baru.
@layer
sedang beraksi
Contoh ini menunjukkan kemampuan lapisan cascade, menggunakan @layer
. Ada beberapa link yang ditampilkan: beberapa tanpa nama class tambahan yang diterapkan, satu dengan class .link
, dan satu dengan class .pink
. CSS kemudian menambahkan tiga lapisan: base
, typography
, dan utilities
sebagai berikut:
@layer base {
a {
font-weight: 800;
color: red; /* ignored */
}
.link {
color: blue; /* ignored */
}
}
@layer typography {
a {
color: green; /* styles *all* links */
}
}
@layer utilities {
.pink {
color: hotpink; /* styles *all* .pink's */
}
}
Pada akhirnya, semua link berwarna hijau atau merah muda. Hal ini karena: meskipun .link
memiliki kekhususan tingkat pemilih yang lebih tinggi daripada a
, ada gaya warna pada a
dalam @layer
prioritas yang lebih tinggi. a { color: green }
mengganti .link { color: blue }
saat aturan hijau berada di lapisan setelah aturan biru.
Prioritas lapisan mengalahkan kekhususan elemen.
Mengatur lapisan
Anda dapat mengatur lapisan langsung di halaman, seperti yang ditunjukkan di atas, atau Anda dapat mengaturnya di bagian atas file.
Urutan lapisan ditetapkan saat pertama kali setiap nama lapisan muncul dalam kode Anda.
Artinya, jika Anda menambahkan kode berikut ke bagian atas file, semua link akan berwarna merah, dan link dengan class .link
akan berwarna biru:
@layer utilities, typography, base;
Hal ini karena urutan lapisan sekarang dibalik, menempatkan utilitas terlebih dahulu dan dasar terakhir. Oleh karena itu, aturan gaya di lapisan base
akan selalu memiliki kekhususan yang lebih tinggi daripada aturan gaya di lapisan tipografi. Link tersebut tidak lagi berwarna hijau, tetapi merah atau biru.
Mengatur impor
Cara lain untuk menggunakan @layer
adalah dengan file impor. Anda dapat melakukannya secara langsung saat mengimpor gaya, menggunakan fungsi layer()
seperti dalam contoh berikut.:
/* Base */
@import '../styles/base/normalize.css' layer(base); /* normalize or rest file */
@import '../styles/base/base.css' layer(base); /* body and base styles */
@import '../styles/base/theme.css' layer(theme); /* theme variables */
@import '../styles/base/typography.css' layer(theme); /* theme typography */
@import '../styles/base/utilities.css' layer(utilities); /* base utilities */
/* Layouts */
@import '../styles/components/post.css' layer(layouts); /* post layout */
/* Components */
@import '../styles/components/cards.css' layer(components); /* imports card */
@import '../styles/components/footer.css' layer(components); /* footer component */
Cuplikan kode di atas memiliki tiga lapisan: base
,layouts
, dan components
. File normalisasi, tema, dan tipografi di base
, dengan file post
di layouts
, serta cards
dan footer
di components
. Saat file diimpor, lapisan dibuat instance-nya menggunakan fungsi lapisan. Pendekatan alternatifnya adalah mengatur lapisan di bagian atas file, mendeklarasikannya sebelum impor apa pun:
@layer base,
theme,
layouts,
components,
utilities;
Sekarang, urutan @import
gaya Anda tidak akan memengaruhi urutan lapisan, karena sudah ditetapkan pada instance pertama nama lapisan. Jadi, Anda tidak perlu khawatir lagi. Anda tetap dapat menetapkan file yang diimpor ke lapisan tertentu, tetapi pengurutannya sudah ditetapkan.
Lapisan dan kaskade
Mari kita mundur sejenak dan melihat tempat lapisan digunakan sehubungan dengan kaskade yang lebih luas:
Urutan prioritasnya adalah sebagai berikut:
- Agen Pengguna normal (prioritas terendah)
- Pengguna Lokal @lapisan
- Pengguna Lokal normal
- Penulis @layers
- Penulis normal
- Penulis !important
- Author @layer !important
- Pengguna Lokal !important
- User Agent !important** (prioritas tertinggi)
Anda mungkin melihat di sini bahwa gaya @layer !important
terbalik. Gaya berlapis memiliki prioritas yang lebih tinggi, bukan kurang spesifik daripada gaya non-berlapis (normal). Hal ini karena cara kerja !important
dalam cascade: !important
akan merusak cascade normal dalam stylesheet Anda dan membalikkan kekhususan tingkat lapisan normal (prioritas).
Lapisan bertingkat
Lapisan juga dapat disusun bertingkat dalam lapisan lain. Contoh berikut berasal dari penjelasan Lapisan Cascade dari Miriam Suzanne:
@layer default {
p { max-width: 70ch; }
}
@layer framework {
@layer default {
p { margin-block: 0.75em; }
}
p { margin-bottom: 1em; }
}
Dalam cuplikan kode di atas, Anda dapat mengakses framework.default
, menggunakan .
sebagai penanda lapisan default
yang disusun bertingkat dalam framework
. Anda juga dapat menulisnya dalam format yang lebih singkat:
@layer framework.default {
p { margin-block: 0.75em }
}
Lapisan dan urutan lapisan yang dihasilkan adalah:
- default
framework.default
framework
tidak berlapis- tidak berlapis
Hal yang perlu diperhatikan
Lapisan kaskade dapat sangat berguna jika Anda menggunakannya dengan benar, tetapi juga dapat menyebabkan kebingungan tambahan dan hasil yang tidak terduga. Perhatikan hal-hal berikut saat menggunakan lapisan cascade:
Aturan 1: Jangan gunakan @layer
untuk cakupan
Lapisan cascade tidak menyelesaikan cakupan. Jika Anda memiliki file CSS dengan @layer
, misalnya card.css
, dan ingin menata gaya semua link dalam kartu, jangan tulis gaya seperti:
a {
…
}
Tindakan ini akan menyebabkan semua tag a
dalam file Anda mendapatkan penggantian ini. Anda tetap harus menentukan cakupan gaya dengan benar:
.card a {
…
}
Aturan 2: lapisan cascade diurutkan di belakang CSS tanpa lapisan
Perlu diperhatikan bahwa file CSS berlapis tidak akan mengganti CSS tanpa lapisan. Ini adalah keputusan yang disengaja untuk mempermudah pengenalan lapisan dengan cara yang lebih masuk akal untuk digunakan dengan codebase yang ada. Misalnya, menggunakan file reset.css
adalah titik awal dan kasus penggunaan yang baik untuk lapisan cascade.
Aturan 3: !important
membalik kekhususan cascade
Meskipun gaya berlapis kurang spesifik daripada gaya tanpa lapisan secara umum, penggunaan !important
akan membalikkan hal ini. Dalam lapisan, deklarasi dengan aturan !important
lebih spesifik daripada gaya tanpa lapisan.
Dalam hal ini, gaya !important
akan membalikkan kekhususannya. Diagram di atas menunjukkan hal ini sebagai referensi: author @layers memiliki prioritas yang lebih rendah daripada author normal yang memiliki prioritas yang lebih rendah daripada author !important yang memiliki prioritas yang lebih rendah daripada author @layer !important.
Jika Anda memiliki beberapa lapisan, lapisan pertama dengan !important
akan diprioritaskan !important
dan menjadi gaya yang paling spesifik.
Aturan 4: Pahami titik injeksi
Karena urutan lapisan ditetapkan saat pertama kali setiap nama lapisan muncul dalam kode Anda, jika Anda menempatkan deklarasi @layer
setelah mengimpor dan menetapkan layer()
, atau setelah pernyataan @layer
yang berbeda, deklarasi tersebut dapat diabaikan. Tidak seperti di CSS, yang menerapkan aturan gaya paling bawah di halaman untuk lapisan kaskade, urutan ditetapkan pada instance pertama.
Ini dapat berupa daftar, blok lapisan, atau impor. Jika Anda menempatkan @layer
setelah daftar impor dengan layer()
, tindakan ini tidak akan melakukan apa pun. Menempatkannya di bagian atas file akan membuatnya menetapkan urutan lapisan, dan membantu Anda melihat lapisan dalam arsitektur dengan jelas.
Aturan #5: Perhatikan kekhususan Anda
Dengan lapisan kaskade, pemilih yang kurang spesifik (seperti a
) akan mengganti pemilih yang lebih spesifik (seperti .link
) jika pemilih yang kurang spesifik tersebut berada di lapisan yang lebih spesifik. Pertimbangkan hal berikut:
a
di layer(components)
akan mengganti .pink
di layer(utilities)
jika: @layer utilities, components
ditentukan. Meskipun merupakan bagian yang disengaja dari API, hal ini dapat membingungkan dan membuat frustrasi jika Anda tidak mengharapkannya.
Jadi, jika Anda menulis class utilitas, selalu sertakan class tersebut sebagai lapisan tingkat tinggi daripada komponen yang ingin Anda ganti. Anda mungkin berpikir, “Saya baru saja menambahkan class .pink
ini untuk mengubah warna, tetapi tidak diterapkan”.
Pelajari lapisan cascade lebih lanjut
Anda juga dapat melihat referensi berikut untuk mempelajari lebih lanjut lapisan cascade: