Penyebaran CSS

Salah satu fitur praprosesor CSS favorit kami kini terintegrasi dalam bahasa: aturan gaya bertingkat.

Adam Argyle
Adam Argyle

Sebelum pembuatan bertingkat, setiap pemilih harus dideklarasikan secara eksplisit, secara terpisah dari satu sama lain. Hal ini menyebabkan pengulangan, stylesheet massal, dan penulisan yang tersebar pengalaman yang lancar bagi developer.

Sebelum
.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

.nesting > .is > .awesome {
  color: deeppink;
}

Setelah penyusunan, pemilih dapat aturan gaya yang berkelanjutan dan terkait dengannya dapat dikelompokkan di dalamnya.

Setelah
.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

Coba ini di browser.

Penyusunan bertingkat membantu developer dengan mengurangi kebutuhan pemilih berulang sekaligus penempatan yang sama pada aturan gaya untuk elemen-elemen terkait. Hal ini juga dapat membantu gaya mencocokkan HTML yang ditargetkan. Jika komponen .nesting di contoh sebelumnya adalah dihapus dari proyek, Anda bisa menghapus seluruh grup alih-alih mencari untuk instance pemilih terkait.

Pemberian bertingkat dapat membantu: - Organisasi - Mengurangi ukuran file - Pemfaktoran ulang

Nesting tersedia mulai Chrome 112 dan juga dapat dicoba di Safari Technical Preview 162.

Memulai CSS Nesting

Sepanjang sisa postingan ini, {i>sandbox<i} demo berikut digunakan untuk membantu Anda memvisualisasikan pilihan. Dalam status {i>default<i} ini, tidak ada yang dipilih dan semuanya terlihat. Dengan memilih berbagai bentuk dan ukuran, Anda dapat berlatih sintaks{i> <i}dan melihat penggunaannya.

Grid berwarna-warni dari lingkaran kecil dan besar, segitiga, dan persegi.

Di dalam sandbox terdapat lingkaran, segitiga, dan persegi. Ada yang kecil, sedang atau besar. Warna lainnya berwarna biru, merah muda, atau ungu. Semua objek tersebut berada di dalam .demo yang memuat elemen. Berikut ini adalah pratinjau elemen HTML yang akan Anda penargetan.

<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 bertingkat

CSS bersarang memungkinkan Anda untuk mendefinisikan gaya untuk 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 yang disusun bertingkat akan hanya berlaku untuk elemen yang merupakan turunan dari elemen dengan class .parent.

Contoh ini dapat juga ditulis menggunakan simbol &, untuk secara eksplisit menunjukkan di mana kelas induk harus ditempatkan.

.parent {
  color: blue;

  & .child {
    color: red;
  }
}

Kedua contoh tersebut secara fungsional setara dan alasan Anda memiliki opsi akan menjadi lebih jelas seiring dengan contoh-contoh lanjutan yang dibahas dalam artikel ini.

Memilih lingkaran

Untuk contoh pertama ini, tugasnya adalah menambahkan gaya untuk memudar dan memburamkan hanya lingkaran di dalam demo.

Tanpa penyusunan bertingkat, CSS saat ini:

.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 menjadi kabur dan hampir tidak terlihat:

Grid bentuk-bentuk yang berwarna-warni tidak lagi memiliki lingkaran,
    di latar belakang yang 
sangat redup.
Coba demo

Memilih segitiga dan persegi

Tugas ini mengharuskan pemilihan beberapa elemen bertingkat, juga disebut pemilih grup.

Tanpa penyusunan bertingkat, CSS saat ini memiliki 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 adalah 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:

{i>Grid<i} bentuk warna-warni hanya tersisa 
dengan lingkaran,
    semua bentuk lainnya hampir tidak terlihat.
Coba demo

Memilih segitiga dan lingkaran besar

Tugas ini memerlukan pemilih gabungan, dengan elemen harus memiliki kedua kelas agar dapat dipilih.

Tanpa penyusunan bertingkat, CSS saat ini:

.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 adalah 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:

Petak berwarna-warni hanya menampilkan bentuk kecil dan sedang.
Coba demo
Tips pro dengan pemilih gabungan dan bertingkat

Simbol & adalah teman Anda di sini karena menunjukkan secara eksplisit cara menggabungkan iklan bertingkat pemilih. 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 Anda harapkan. Alasannya adalah jika & tidak menentukan hasil gabungan .lg.triangle, .lg.circle yang diinginkan, hasil sebenarnya adalah .lg .triangle, .lg .circle; pemilih turunan.

Memilih semua bentuk kecuali yang berwarna merah muda

Tugas ini memerlukan class pseudo fungsional negasi, dengan elemen tidak boleh memiliki pemilih yang ditentukan.

Tanpa penyusunan bertingkat, CSS saat ini:

.demo :not(.pink) {
  opacity: .25;
  filter: blur(25px);
}

Dengan penyusunan bertingkat, berikut adalah 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:

Petak berwarna-warni kini menjadi monokrom, hanya menampilkan bentuk merah muda.
Coba demo
Presisi dan fleksibilitas dengan &

Misalnya Anda ingin menargetkan .demo dengan pemilih :not(). & diperlukan untuk bahwa:

.demo {
  &:not() {
    ...
  }
}

Tindakan ini menggabungkan .demo dan :not() menjadi .demo:not(), dibandingkan dengan yang sebelumnya contoh yang memerlukan .demo :not(). Pengingat ini dibuat sangat penting ketika ingin menyarangkan interaksi :hover.

.demo {
  &:hover {
    /* .demo:hover */
  }

  :hover {
    /* .demo :hover */
  }
}

Contoh penyusunan bertingkat lainnya

Spesifikasi CSS untuk pembuatan bertingkat adalah yang dilengkapi dengan lebih banyak contoh. Jika Anda ingin mempelajari lebih lanjut tentang {i>syntax<i} melalui contoh, contoh ini mencakup berbagai contoh yang valid dan tidak valid.

Beberapa contoh berikutnya akan secara singkat memperkenalkan fitur CSS bertingkat, untuk membantu Anda memahami berbagai kemampuan yang diberikannya.

Menyusun @media

Bergerak ke area yang berbeda pada stylesheet yang berbeda akan sangat mengganggu untuk menemukan kondisi kueri media yang memodifikasi pemilih dan gayanya. Gangguan itu hilang dengan kemampuan untuk menyarangkan kondisi tepat di dalam konteks.

Untuk kemudahan sintaksis, jika kueri media bertingkat hanya memodifikasi gaya untuk konteks pemilih saat ini, maka sintaks minimal dapat digunakan.

.card {
  font-size: 1rem;

  @media (width >= 1024px) {
    font-size: 1.25rem;
  }
}

Penggunaan & 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 .large kartu untuk menunjukkan fitur bertingkat tambahan akan terus berfungsi.

Pelajari lebih lanjut cara membuat @rules lebih lanjut.

Bertingkat di mana saja

Semua contoh sampai saat ini adalah lanjutan atau ditambahkan ke konteks sebelumnya. Anda dapat sepenuhnya mengubah atau mengatur ulang konteksnya jika diperlukan.

.card {
  .featured & {
    /* .featured .card */
  }
}

Simbol & mewakili referensi ke objek pemilih (bukan string) dan dapat ditempatkan di mana saja dalam pemilih bertingkat. Bahkan dapat ditempatkan beberapa waktu:

.card {
  .featured & & & {
    /* .featured .card .card .card */
  }
}

Meskipun contoh ini tampak sedikit tidak berguna, pasti ada skenario di mana dapat mengulang konteks pemilih.

Contoh penyusunan bertingkat tidak valid

Ada beberapa skenario sintaksis bertingkat yang tidak valid dan mungkin mengejutkan Anda jika Anda selama ini bersarang pada praprosesor.

Penyusunan dan penyambungan

Banyak konvensi penamaan class CSS yang mengandalkan kemampuan {i>nesting<i} untuk menggabungkan atau menambahkan pemilih seolah-olah itu adalah string. Hal ini tidak berfungsi dalam nesting CSS karena pemilih bukan string, mereka adalah 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, lalu terus disusun bertingkat. Contoh sebelumnya hanya berakhir dengan daftar pemilih. Tidak ada yang tidak valid dalam contoh penyusunan bertingkat ini, tetapi ada detail implementasi yang berpotensi rumit tentang penyusunan bertingkat di dalam daftar pemilih, terutama yang menyertakan pemilih ID.

Agar intent penyusunan bertingkat berfungsi, setiap daftar pemilih yang bukan bagian bertingkat paling dalam, akan digabungkan dengan :is() oleh browser. Pembungkus ini mempertahankan pengelompokan daftar pemilih dalam konteks yang ditulis. Efek samping pengelompokan ini, :is(.one, #two), adalah bahwa pengelompokan ini mengadopsi kekhususan skor tertinggi dalam pemilih dalam tanda kurung. Inilah cara :is() selalu bekerja, tetapi mungkin akan mengejutkan saat menggunakan sintaksis bertingkat karena itu tidak persis seperti yang ditulis. Triknya diringkas; bersarang dengan ID dan daftar pemilih dapat menghasilkan pemilih kekhususan yang sangat tinggi.

Untuk meringkas contoh rumit dengan jelas, blok bertingkat sebelumnya akan diterapkan ke dokumen sebagai berikut:

:is(.one, #two) .three {
  /* some styles */
}

Waspadalah atau ajari linter Anda untuk memperingatkan saat membuat bertingkat di dalam daftar pemilih yang menggunakan pemilih ID, kekhususan semua tingkatan dalam daftar pemilih tersebut akan tinggi.

Menggabungkan penyusunan bertingkat dan deklarasi

Pertimbangkan blok CSS bertingkat berikut:

.card {
  color: green;
  & { color: blue; }
  color: red;
}

Warna elemen .card akan menjadi blue.

Setiap deklarasi gaya yang dicampur diangkat ke atas, seolah-olah ditulis sebelum terjadi penyusunan bertingkat. Detail selengkapnya dapat ditemukan di spesifikasi.

Ada cara untuk melakukannya. Kode berikut menggabungkan tiga gaya warna di &, yang mempertahankan urutan {i>cascade<i} seperti yang diinginkan penulis. Warna Elemen .card akan berwarna merah.

.card {
  color: green;
  & { color: blue; }
  & { color: red; }
}

Bahkan, sebaiknya gabungkan semua gaya yang mengikuti penyusunan bertingkat dengan &.

.card {
  color: green;

  @media (prefers-color-scheme: dark) {
    color: lightgreen;
  }

  & {
    aspect-ratio: 4/3;
  }
}

Deteksi fitur

Ada dua cara hebat untuk mendeteksi penyusunan bertingkat CSS: menggunakan penyusunan bertingkat atau menggunakan @supports untuk memeriksa kemampuan penguraian pemilih bertingkat.

Screenshot demo Codepen Bramus, menanyakan apakah browser Anda mendukung
  Penyusunan bertingkat (nesting) CSS. Di bawah pertanyaan itu terdapat kotak hijau, yang menandakan dukungan.

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 hebat yang menunjukkan strategi ini.

Proses debug dengan Chrome DevTools

Dukungan saat ini di DevTools untuk pembuatan bertingkat minimal. Saat ini Anda akan menemukan gaya ditampilkan di panel Styles seperti yang diharapkan, tetapi melacak tingkatan dan konteks pemilih lengkapnya belum didukung. Kami memiliki desain dan rencana untuk buat ini transparan dan jelas.

Screenshot sintaksis penyusunan bertingkat Chrome DevTools.

Chrome 113 berencana menyediakan dukungan tambahan untuk pembuatan bertingkat CSS. Terus ikuti perkembangannya.

Acara mendatang

CSS Nesting hanya tersedia di versi 1. Versi 2 akan memperkenalkan lebih banyak sugar sintaksis dan kemungkinan lebih sedikit aturan untuk menghafal. Ada banyak permintaan agar penguraian bertingkat tidak dibatasi atau mengalami saat-saat rumit.

Peningkatan adalah peningkatan besar pada bahasa CSS. Memiliki implikasi penulisan ke hampir semua aspek arsitektur CSS. Dampak besar ini perlu diketahui dieksplorasi dan dipahami sebelum versi 2 dapat ditentukan secara efektif.

Sebagai pengingat terakhir, berikut demonya yang menggunakan @scope, pembuatan bertingkat, dan @layer secara bersamaan. Semuanya sangat menarik!

Kartu terang dengan latar belakang abu-abu. Kartu ini memiliki judul dan teks,
  beberapa tombol tindakan, dan gambar 
bergaya cyber punk.