Reaktivitas Token Desain

Latar Belakang & Ringkasan

Sering kali, penulis perlu membuat perubahan kontekstual pada desain komponen. Secara historis, penulis perlu menggunakan pemilih untuk menerapkan perubahan tersebut. Hal ini sering kali berarti bahwa meskipun banyak token desain mereka dapat ada sebagai properti kustom, token desain tingkat tinggi hanya dapat dienkode sebagai pola pemilih (yaitu menggunakan nama class atau konvensi atribut) atau sebagai props/konteks dalam framework JavaScript.

Kueri gaya penampung memungkinkan penulis menata gaya elemen berdasarkan nilai properti kustom yang dihitung dari elemen ancestor. Artinya, penulis dapat menulis nilai token desain yang bermakna dalam stylesheet mereka, bukan mengandalkan markup atau JavaScript untuk presentasi.

Cara menerapkan

Menerapkan token desain reaktif menggunakan kueri gaya penampung cukup mudah:

  1. Tetapkan token desain tingkat tinggi sebagai properti kustom pada penampung. Properti ini tidak harus berupa properti kustom terdaftar.
  2. Gunakan aturan @container style() untuk mengkueri nilai properti kustom tersebut.
  3. Terapkan gaya yang sesuai ke elemen turunan dalam penampung.

Beberapa hal yang harus diingat:

  • Penampung yang dikueri dengan kueri gaya tidak perlu memiliki container-type atau container-name yang ditetapkan, tetapi container-name dapat memungkinkan kueri yang lebih spesifik.
  • Penampung itu sendiri tidak dapat diberi gaya oleh kueri gaya penampung.

Berikut adalah contoh dasar langkah-langkah penerapan di atas.

<div class="features">
  <div class="card"></div>
  <div class="card"></div>
</div>
<div class="bugs">
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
</div>
.features {
  --density: spacious;
}

.bugs {
  --density: compact;
}

@container style(--density: compact) {
  .card {
    padding: 8px;
  }
}

@container style(--density: spacious) {
  .card {
    padding: 24px;
  }
}

Strategi penggantian

Sebelum ada dukungan Baseline untuk kueri gaya penampung, TIDAK DIREKOMENDASIKAN untuk menggunakannya pada fitur inti yang harus tersedia di semua browser, karena tidak mudah untuk membuat pengganti yang tidak mengurangi manfaatnya atau yang memiliki batasan tersendiri. Misalnya, jika preferensi pengguna terkait kepadatan UI tidak dianggap sebagai fitur inti yang harus tersedia di semua pengalaman, kueri gaya penampung dapat digunakan untuk menerapkan fitur tersebut tanpa penggantian.

Menggunakan pemilih

Untuk fitur inti, pendekatan alternatif menggunakan pemilih harus digunakan. Contoh ini menggunakan atribut data-density untuk mengenkode token desain kepadatan dalam markup, bukan sebagai properti kustom:

<div class="features" data-density="spacious">
  <div class="card"></div>
  <div class="card"></div>
</div>
<div class="bugs" data-density="compact">
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
</div>
/* This example uses `:where()` to avoid increasing specificity */
:where([data-density="compact"]) .card {
  padding: var(--card-padding-compact);
}

:where([data-density="spacious"]) .card {
  padding: var(--card-padding-spacious);
}

Batasan utama pendekatan penggantian ini adalah tidak mendukung elemen bertingkat dengan atribut data-density yang ditetapkan, karena kekhususan pemilihnya sama, urutan kemunculan akan digunakan untuk menentukan gaya (yaitu [data-density="spacious"] akan selalu lebih diutamakan daripada [data-density="compact"]).

Menggunakan kueri gaya sebagai progressive enhancement

Meskipun TIDAK DIREKOMENDASIKAN, jika Anda ingin menggunakan kueri gaya sebagai progressive enhancement untuk fitur inti, Anda dapat membuat beberapa properti kustom untuk menghindari duplikasi, lalu menyertakan kueri gaya setelahnya. Pastikan pendekatan penggantian menggunakan :where() saat memilih elemen penampung untuk menghindari peningkatan spesifisitas.

.card {
  --card-padding-compact: 8px;
  --card-padding-spacious: 24px;
}

:where([data-density="compact"]) .card {
  padding: var(--card-padding-compact);
}

:where([data-density="spacious"]) .card {
  padding: var(--card-padding-spacious);
}

/* Use style queries as a progressive enhancement: same specificity, so order of appearance is used */

@container style(--density: compact) {
  .card {
    padding: var(--card-padding-compact);
  }
}

@container style(--density: spacious) {
  .card {
    padding: var(--card-padding-spacious);
  }
}

Pemeriksaan fitur hanya dengan CSS

Jika Anda perlu memeriksa fitur kueri gaya penampung untuk menampilkan beberapa UI yang mengandalkannya secara bersyarat, Anda dapat menggunakan kueri gaya untuk melakukannya:

:root {
  --style-queries-supported: check;
}

.density-toggle {
  display: none;
}

@container style(--style-queries-supported) {
  .density-toggle {
    display: revert;
  }
}

Pemeriksaan fitur dengan JavaScript

Untuk pemeriksaan fitur dengan JavaScript, prosesnya sedikit lebih rumit karena antarmuka CSSContainerRule sudah ada sebelum penambahan kueri gaya penampung, sehingga tidak dapat diandalkan untuk tujuan ini. Sebagai gantinya, Anda harus memeriksa nilai yang dihitung dari properti yang diketahui yang ditetapkan dengan kueri gaya.

Contoh ini menggunakan properti kustom karena tidak akan memiliki efek visual:

:root {
  --style-queries-supported: check;
}

@container style(--style-queries-supported: check) {
  body {
    --style-queries-supported: yes;
  }
}

Kemudian, periksa nilai yang dihitung di JavaScript seperti ini:

if (getComputedStyle(document.body).getPropertyValue("--style-queries-supported") === "yes") {
  // Use container style queries
} else {
  // Use fallback strategy
}