Salah satu fitur praprosesor CSS favorit kami kini telah ditanamkan ke dalam bahasa: aturan gaya bertingkat.
Sebelum dibuat bertingkat, setiap pemilih harus dideklarasikan secara eksplisit, secara terpisah satu sama lain. Hal ini menyebabkan pengulangan, bulksheet dalam jumlah besar, dan pengalaman penulisan yang tersebar.
.nesting { color: hotpink; } .nesting > .is { color: rebeccapurple; } .nesting > .is > .awesome { color: deeppink; }
Setelah bertingkat, pemilih dapat dilanjutkan dan aturan gaya yang terkait dapat dikelompokkan di dalamnya.
.nesting { color: hotpink; > .is { color: rebeccapurple; > .awesome { color: deeppink; } } }
Penyusunan bertingkat membantu developer mengurangi kebutuhan untuk mengulangi pemilih sekaligus
menemukan aturan gaya bersama untuk elemen terkait. Hal ini juga dapat membantu gaya agar cocok dengan
HTML yang ditargetkan. Jika komponen .nesting
dalam contoh sebelumnya
dihapus dari project, Anda dapat menghapus seluruh grup, bukan menelusuri
file untuk instance pemilih terkait.
Nesting dapat membantu: - Organisasi - Mengurangi ukuran file - Pemfaktoran ulang
Nesting tersedia mulai Chrome 112 dan juga tersedia untuk dicoba di Safari Technical Preview 162.
Memulai CSS Nesting
Sepanjang postingan ini,sandbox demo berikut digunakan untuk membantu Anda memvisualisasikan pilihan. Dalam status default ini, tidak ada yang dipilih dan semuanya akan terlihat. Dengan memilih berbagai bentuk dan ukuran, Anda dapat berlatih sintaksis dan melihat cara kerjanya.
Di dalam sandbox terdapat lingkaran, segitiga, dan persegi. Ada yang kecil, sedang,
atau besar. Lainnya berwarna biru, merah muda, atau ungu. Semuanya berada di dalam elemen
yang berisi .demo
. Berikut adalah pratinjau elemen HTML yang akan Anda
targetkan.
<div class="demo">
<div class="sm triangle pink"></div>
<div class="sm triangle blue"></div>
<div class="square blue"></div>
<div class="sm square pink"></div>
<div class="sm square blue"></div>
<div class="circle pink"></div>
…
</div>
Contoh tingkatan
Penyusunan bertingkat CSS memungkinkan Anda menentukan gaya untuk sebuah elemen dalam konteks pemilih lain.
.parent {
color: blue;
.child {
color: red;
}
}
Dalam contoh ini, pemilih class .child
disusun bertingkat dalam
pemilih class .parent
. Artinya, pemilih .child
bertingkat hanya akan
diterapkan pada elemen yang merupakan turunan elemen dengan class .parent
.
Contoh ini juga dapat ditulis menggunakan simbol &
, untuk secara eksplisit
menandakan tempat class induk harus ditempatkan.
.parent {
color: blue;
& .child {
color: red;
}
}
Kedua contoh ini setara secara fungsional dan alasan Anda memiliki opsi ini akan menjadi lebih jelas seiring dengan pembahasan contoh yang lebih lanjut dalam artikel ini.
Memilih lingkaran
Untuk contoh pertama, tugasnya adalah menambahkan gaya untuk memudar dan memburamkan hanya lingkaran di dalam demo.
Tanpa penyusunan bertingkat, CSS kini:
.demo .circle {
opacity: .25;
filter: blur(25px);
}
Dengan penyusunan bertingkat, ada dua cara yang valid:
/* & is explicitly placed in front of .circle */
.demo {
& .circle {
opacity: .25;
filter: blur(25px);
}
}
atau
/* & + " " space is added for you */
.demo {
.circle {
opacity: .25;
filter: blur(25px);
}
}
Hasilnya, semua elemen di dalam .demo
dengan class .circle
diburamkan dan hampir tidak terlihat:
Memilih segitiga dan persegi
Tugas ini mengharuskan Anda memilih beberapa elemen bertingkat, juga disebut pemilih grup.
Tanpa penyusunan bertingkat, CSS saat ini, ada dua cara:
.demo .triangle,
.demo .square {
opacity: .25;
filter: blur(25px);
}
atau menggunakan :is()
/* grouped with :is() */
.demo :is(.triangle, .square) {
opacity: .25;
filter: blur(25px);
}
Dengan penyusunan bertingkat, berikut ini dua cara yang valid:
.demo {
& .triangle,
& .square {
opacity: .25;
filter: blur(25px);
}
}
atau
.demo {
.triangle, .square {
opacity: .25;
filter: blur(25px);
}
}
Hasilnya, hanya elemen .circle
yang tetap berada di dalam .demo
:
Memilih segitiga dan lingkaran besar
Tugas ini memerlukan pemilih gabungan, dengan elemen harus memiliki kedua class agar dapat dipilih.
Tanpa penyusunan bertingkat, CSS kini:
.demo .lg.triangle,
.demo .lg.square {
opacity: .25;
filter: blur(25px);
}
atau
.demo .lg:is(.triangle, .circle) {
opacity: .25;
filter: blur(25px);
}
Dengan penyusunan bertingkat, berikut ini dua cara yang valid:
.demo {
.lg.triangle,
.lg.circle {
opacity: .25;
filter: blur(25px);
}
}
atau
.demo {
.lg {
&.triangle,
&.circle {
opacity: .25;
filter: blur(25px);
}
}
}
Hasilnya, semua segitiga dan lingkaran besar disembunyikan di dalam .demo
:
Tips pro dengan pemilih gabungan dan nesting
Simbol &
adalah teman Anda di sini karena menunjukkan secara eksplisit cara menggabungkan pemilih
bertingkat. Perhatikan contoh berikut:
.demo {
.lg {
.triangle,
.circle {
opacity: .25;
filter: blur(25px);
}
}
}
Meskipun merupakan cara yang valid untuk menyusun bertingkat, hasilnya tidak akan cocok dengan elemen yang mungkin Anda harapkan.
Alasannya adalah bahwa tanpa &
untuk menentukan hasil yang diinginkan dari .lg.triangle,
.lg.circle
yang digabungkan, hasil sebenarnya adalah .lg .triangle, .lg
.circle
; pemilih turunan.
Memilih semua bentuk kecuali yang merah muda
Tugas ini memerlukan class pseudo fungsional negasi, dengan elemen tidak boleh memiliki pemilih yang ditentukan.
Tanpa penyusunan bertingkat, CSS kini:
.demo :not(.pink) {
opacity: .25;
filter: blur(25px);
}
Dengan penyusunan bertingkat, berikut ini dua cara yang valid:
.demo {
:not(.pink) {
opacity: .25;
filter: blur(25px);
}
}
atau
.demo {
& :not(.pink) {
opacity: .25;
filter: blur(25px);
}
}
Hasilnya, semua bentuk yang tidak berwarna merah muda disembunyikan di dalam .demo
:
Presisi dan fleksibilitas dengan &
Misalnya Anda ingin menargetkan .demo
dengan pemilih :not()
. &
diperlukan untuk
hal berikut:
.demo {
&:not() {
...
}
}
Ini menggabungkan .demo
dan :not()
ke .demo:not()
, berbeda dengan contoh sebelumnya yang memerlukan .demo :not()
. Pengingat ini dibuat sangat penting saat
ingin menyarangkan interaksi :hover
.
.demo {
&:hover {
/* .demo:hover */
}
:hover {
/* .demo :hover */
}
}
Contoh tingkatan lainnya
Spesifikasi CSS untuk penyusunan bertingkat dikemas dengan lebih banyak contoh. Jika Anda ingin mempelajari lebih lanjut sintaksis melalui contoh, panduan ini mencakup berbagai contoh yang valid dan tidak valid.
Beberapa contoh berikutnya akan secara singkat memperkenalkan fitur penyusunan bertingkat CSS, untuk membantu Anda memahami cakupan kemampuan yang tersedia.
Menyusun @media
Berpindah ke area stylesheet yang lain dapat sangat mengganggu untuk menemukan kondisi kueri media yang mengubah pemilih dan gayanya. Gangguan tersebut hilang dengan kemampuan untuk menumpuk kondisi tepat di dalam konteks.
Untuk kemudahan sintaksis, jika kueri media bertingkat hanya mengubah gaya untuk konteks pemilih saat ini, sintaksis minimal dapat digunakan.
.card {
font-size: 1rem;
@media (width >= 1024px) {
font-size: 1.25rem;
}
}
Menggunakan &
secara eksplisit juga dapat digunakan:
.card {
font-size: 1rem;
@media (width >= 1024px) {
&.large {
font-size: 1.25rem;
}
}
}
Contoh ini menunjukkan sintaksis yang diperluas dengan &
, sekaligus menargetkan kartu .large
untuk menunjukkan fitur bertingkat tambahan yang terus berfungsi.
Pelajari @aturan bertingkat lebih lanjut.
Bersarang di mana saja
Semua contoh hingga tahap ini merupakan lanjutan atau ditambahkan ke konteks sebelumnya. Anda dapat sepenuhnya mengubah atau mengatur ulang konteks jika diperlukan.
.card {
.featured & {
/* .featured .card */
}
}
Simbol &
mewakili referensi ke objek pemilih (bukan string) dan
dapat ditempatkan di mana saja dalam pemilih bertingkat. Kode ini bahkan dapat ditempatkan beberapa
kali:
.card {
.featured & & & {
/* .featured .card .card .card */
}
}
Meskipun contoh ini agak tidak berguna, tentu saja ada beberapa skenario ketika mampu mengulangi konteks pemilih akan sangat berguna.
Contoh tingkatan yang tidak valid
Ada beberapa skenario sintaksis bertingkat yang tidak valid dan mungkin mengejutkan Anda jika Anda telah menyarangkan praprosesor.
Nesting dan penyambungan
Banyak konvensi penamaan class CSS bergantung pada kemampuan penyusunan bertingkat untuk dapat menggabungkan atau menambahkan pemilih seolah-olah pemilih adalah string. Cara ini tidak berfungsi dalam penyusunan bertingkat CSS, karena pemilih bukan string, melainkan referensi objek.
.card {
&--header {
/* is not equal to ".card--header" */
}
}
Penjelasan yang lebih mendalam dapat ditemukan di spesifikasi.
Contoh penyusunan bertingkat yang rumit
Bertingkat dalam daftar pemilih dan :is()
Pertimbangkan blok CSS bertingkat berikut:
.one, #two {
.three {
/* some styles */
}
}
Ini adalah contoh pertama yang dimulai dengan daftar pemilih dan kemudian terus disusun bertingkat lebih lanjut. Contoh sebelumnya hanya diakhiri dengan daftar pemilih. Tidak ada yang tidak valid dalam contoh tingkatan ini, tetapi ada detail implementasi yang berpotensi rumit tentang penyusunan bertingkat di dalam daftar pemilih, terutama yang menyertakan pemilih ID.
Agar intent tingkatan berfungsi, daftar pemilih yang bukan bagian dalam yang paling bertingkat, akan digabungkan dengan :is()
oleh browser. Penggabungan ini mempertahankan pengelompokan daftar pemilih dalam konteks yang ditulis. Efek samping dari pengelompokan ini, :is(.one, #two)
, adalah bahwa pengelompokan ini mengadopsi kekhususan skor tertinggi dalam pemilih dalam tanda kurung. Begitulah cara kerja :is()
selalu bekerja, tetapi mungkin mengejutkan saat menggunakan sintaksis bertingkat karena tidak sama persis dengan yang ditulis. Rangkuman triknya; bersarang dengan ID dan daftar pemilih dapat menghasilkan pemilih dengan kekhususan yang sangat tinggi.
Untuk meringkas contoh rumit dengan jelas, blok susunan sebelumnya akan diterapkan ke dokumen sebagai berikut:
:is(.one, #two) .three {
/* some styles */
}
Awasi atau ajari linter untuk memperingatkan saat menyusun bertingkat dalam daftar pemilih yang menggunakan pemilih ID, kekhususan semua tingkatan dalam daftar pemilih tersebut akan tinggi.
Mengombinasikan nesting dan deklarasi
Pertimbangkan blok CSS bertingkat berikut:
.card {
color: green;
& { color: blue; }
color: red;
}
Warna elemen .card
akan menjadi blue
.
Setiap deklarasi gaya campuran diangkat ke atas, seolah-olah ditulis sebelum terjadi tingkatan. Detail selengkapnya dapat ditemukan di spesifikasi.
Ada beberapa cara untuk mengatasinya. Kode berikut menggabungkan tiga gaya warna di &
, yang
mempertahankan urutan menurun seperti yang mungkin diinginkan penulis. Warna
elemen .card
akan berwarna merah.
.card {
color: green;
& { color: blue; }
& { color: red; }
}
Bahkan, sebaiknya gabungkan gaya apa pun yang mengikuti pembuatan bertingkat dengan &
.
.card {
color: green;
@media (prefers-color-scheme: dark) {
color: lightgreen;
}
& {
aspect-ratio: 4/3;
}
}
Deteksi fitur
Ada dua cara yang efektif untuk mendeteksi penyusunan bertingkat CSS: menggunakan penyusunan bertingkat atau menggunakan
@supports
untuk memeriksa kemampuan penguraian pemilih bertingkat.
Menggunakan penyusunan bertingkat:
html {
.has-nesting {
display: block;
}
.no-nesting {
display: none;
}
}
Menggunakan @supports
:
@supports (selector(&)) {
/* nesting parsing available */
}
Kolega saya, Bramus, memiliki Codepen yang bagus yang menunjukkan strategi ini.
Proses debug dengan Chrome DevTools
Dukungan saat ini di DevTools untuk penyarangan minimal. Saat ini, Anda akan menemukan gaya ditampilkan di panel Styles seperti yang diharapkan, tetapi pelacakan bertingkat dan konteks pemilih lengkapnya belum didukung. Kami memiliki desain dan rencana untuk membuatnya transparan dan jelas.
Chrome 113 berencana memiliki dukungan tambahan untuk penyusunan bertingkat CSS. Nantikan kabar terbaru.
Acara mendatang
Penyusunan CSS hanya pada versi 1. Versi 2 akan memperkenalkan lebih banyak sintaksis dan kemungkinan lebih sedikit aturan untuk dihafal. Ada banyak permintaan untuk penguraian bertingkat agar tidak dibatasi atau memiliki momen yang rumit.
Penyusunan (nesting) adalah peningkatan besar pada bahasa CSS. Ini memiliki implikasi penyusunan hampir setiap aspek arsitektur CSS. Dampak besar ini perlu dieksplorasi dan dipahami secara mendalam sebelum versi 2 dapat ditentukan secara efektif.
Sebagai pemikiran terakhir, berikut adalah demo
yang menggunakan @scope
, penyusunan bertingkat, dan @layer
secara bersamaan. Semuanya sangat mengasyikkan!