Penyebaran CSS

Salah satu fitur preprocessor CSS favorit kami kini di-build ke dalam bahasa: aturan gaya bertingkat.

Adam Argyle
Adam Argyle

Sebelum menyusun bertingkat, setiap pemilih harus dideklarasikan secara eksplisit, secara terpisah dari satu sama lain. Hal ini menyebabkan pengulangan, bulk stylesheet, dan pengalaman penulisan yang tersebar.

Sebelum
.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

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

Setelah penyematan, pemilih dapat dilanjutkan dan aturan gaya terkait dapat dikelompokkan di dalamnya.

Setelah
.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

Coba ini di browser.

Penggabungan membantu developer dengan mengurangi kebutuhan untuk mengulangi pemilih sekaligus menempatkan aturan gaya bersama untuk elemen terkait. Hal ini juga dapat membantu gaya 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.

Penetasan dapat membantu: - Pengaturan - Mengurangi ukuran file - Pemfaktoran ulang

Penyusunan bertingkat tersedia mulai Chrome 112 dan juga tersedia untuk dicoba di Pratinjau Teknis Safari 162.

Mulai menggunakan CSS Nesting

Di seluruh postingan ini,sandbox demo berikut digunakan untuk membantu Anda memvisualisasikan pilihan. Dalam status default ini, tidak ada yang dipilih dan semuanya terlihat. Dengan memilih berbagai bentuk dan ukuran, Anda dapat mempraktikkan sintaksis dan melihatnya beraksi.

Petak berwarna-warni yang terdiri dari lingkaran, segitiga, dan persegi kecil dan besar.

Di dalam sandbox terdapat lingkaran, segitiga, dan kotak. Beberapa di antaranya berukuran kecil, sedang, atau besar. Warna lainnya adalah biru, merah muda, atau ungu. Semuanya berada di dalam elemen penampung .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

Dengan CSS nesting, Anda dapat menentukan 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. Ini berarti pemilih .child bertingkat hanya akan diterapkan ke elemen yang merupakan turunan dari elemen dengan class .parent.

Contoh ini juga dapat ditulis menggunakan simbol &, untuk secara eksplisit menunjukkan tempat class induk harus ditempatkan.

.parent {
  color: blue;

  & .child {
    color: red;
  }
}

Kedua contoh ini secara fungsional setara dan alasan Anda memiliki opsi akan menjadi lebih jelas saat contoh yang lebih canggih dipelajari dalam artikel ini.

Memilih lingkaran

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

Tanpa penyusunan bertingkat, CSS saat ini:

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

Dengan tingkatan, 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:

Petak bentuk berwarna-warni tidak lagi memiliki lingkaran,
    dan sangat samar di latar belakang.
Coba demo

Memilih segitiga dan kotak

Tugas ini memerlukan pemilihan beberapa elemen bertingkat, yang 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 tingkatan, 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:

Petak bentuk berwarna-warni hanya berisi lingkaran,
    semua bentuk lainnya hampir tidak terlihat.
Coba demo

Memilih segitiga dan lingkaran besar

Tugas ini memerlukan pemilih gabungan, dengan elemen yang harus memiliki kedua class 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 tingkatan, 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 tingkatan

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 membuat tingkatan, hasilnya tidak akan cocok dengan elemen yang mungkin Anda harapkan. Alasannya adalah tanpa & untuk menentukan hasil .lg.triangle, .lg.circle yang diinginkan yang digabungkan, hasil sebenarnya adalah .lg .triangle, .lg .circle; pemilih turunan.

Memilih semua bentuk kecuali yang berwarna merah muda

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

Tanpa penyusunan bertingkat, CSS saat ini:

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

Dengan tingkatan, 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 bukan merah muda akan 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(). & wajib untuk hal tersebut:

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

Hal ini menggabungkan .demo dan :not() menjadi .demo:not(), tidak seperti contoh sebelumnya yang memerlukan .demo :not(). Pengingat ini dibuat sangat penting saat ingin menyusun interaksi :hover.

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

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

Contoh bertingkat lainnya

Spesifikasi CSS untuk penyusunan bertingkat dikemas dengan lebih banyak contoh. Jika Anda ingin mempelajari sintaksis lebih lanjut melalui contoh, bagian ini mencakup berbagai contoh yang valid dan tidak valid.

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

@media bertingkat

Berpindah ke area lain di stylesheet untuk menemukan kondisi kueri media yang mengubah pemilih dan gayanya dapat sangat mengganggu. Gangguan tersebut akan hilang dengan kemampuan untuk menyusun kondisi tepat di dalam konteks.

Untuk memudahkan 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;
  }
}

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 kartu .large untuk menunjukkan bahwa fitur penyusunan bertingkat tambahan terus berfungsi.

Pelajari lebih lanjut cara mengaitkan @rules.

Menyusun bertingkat di mana saja

Semua contoh hingga saat ini telah dilanjutkan atau ditambahkan ke konteks sebelumnya. Anda dapat sepenuhnya mengubah atau mengatur ulang konteks jika perlu.

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

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

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

Meskipun contoh ini terlihat agak tidak berguna, pasti ada skenario saat dapat 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 membuat bertingkat di preprocessor.

Penyusunan bertingkat dan penyambungan

Banyak konvensi penamaan class CSS mengandalkan tingkatan yang dapat menyambungkan atau menambahkan pemilih seolah-olah itu adalah string. Hal 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

Menyusun 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 lebih lanjut. Contoh sebelumnya hanya berakhir dengan daftar pemilih. Tidak ada yang tidak valid dalam contoh penyusunan bertingkat ini, tetapi ada detail penerapan yang berpotensi rumit tentang penyusunan bertingkat di dalam daftar pemilih, terutama yang menyertakan pemilih ID.

Agar intent penyusunan bertingkat berfungsi, daftar pemilih apa pun yang bukan penyusunan bertingkat paling dalam akan digabungkan dengan :is() oleh browser. Penggabungan 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. Ini adalah cara :is() selalu berfungsi, tetapi mungkin mengejutkan saat menggunakan sintaksis bertingkat karena tidak sama persis dengan yang ditulis. Trik yang diringkas; menyusun bertingkat dengan ID dan daftar pemilih dapat menghasilkan pemilih dengan spesifitas yang sangat tinggi.

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

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

Perhatikan atau ajari lint Anda untuk memperingatkan saat menyusun bertingkat di dalam daftar pemilih yang menggunakan pemilih ID, kekhususan semua penyusunan bertingkat dalam daftar pemilih tersebut akan tinggi.

Mencampurkan deklarasi dan tingkatan

Pertimbangkan blok CSS bertingkat berikut:

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

Warna elemen .card akan menjadi blue.

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

Ada cara untuk mengatasinya. Berikut ini menggabungkan tiga gaya warna dalam &, yang mempertahankan urutan cascade 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 penyusunan bertingkat dengan &.

.card {
  color: green;

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

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

Deteksi fitur

Ada dua cara yang bagus untuk mendeteksi susunan bertingkat CSS: gunakan susunan bertingkat atau gunakan @supports untuk memeriksa kemampuan penguraian pemilih susunan bertingkat.

Screenshot demo Codepen Bramus, yang menanyakan apakah browser Anda mendukung
  CSS nesting. Di bawah pertanyaan tersebut terdapat kotak hijau, yang menandakan dukungan.

Menggunakan tingkatan:

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 pembuatan bertingkat sangat minim. Saat ini, Anda akan menemukan gaya yang ditampilkan di panel Gaya seperti yang diharapkan, tetapi pelacakan tingkat dan konteks pemilih lengkapnya belum didukung. Kami memiliki desain dan rencana untuk membuat hal ini transparan dan jelas.

Screenshot sintaksis bertingkat Chrome DevTools.

Chrome 113 berencana memiliki dukungan tambahan untuk penyusunan bertingkat CSS. Terus ikuti perkembangannya.

Acara mendatang

Penyusunan CSS hanya tersedia di versi 1. Versi 2 akan memperkenalkan lebih banyak sintaksis dan berpotensi lebih sedikit aturan untuk dihafalkan. Ada banyak permintaan agar penguraian tingkat bertingkat tidak terbatas atau memiliki momen yang rumit.

Penyusunan bertingkat adalah peningkatan besar pada bahasa CSS. Hal ini memiliki implikasi penulisan ke hampir setiap aspek arsitektur CSS. Dampak besar ini perlu dipelajari 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 menarik!

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