Menggali Kueri Gaya Kontainer Lebih Dalam

Node Sumber: 1765194

Saya menulis beberapa pemikiran awal tentang kueri gaya wadah beberapa waktu lalu. Ini masih awal. Mereka sudah didefinisikan dalam Spesifikasi Modul Penahanan CSS Level 1 (saat ini dalam status Draf Editor) tetapi masih ada beberapa diskusi luar biasa yang sedang berlangsung.

Ide dasarnya adalah kita dapat mendefinisikan sebuah wadah dan kemudian menerapkan gaya secara kondisional ke turunannya berdasarkan gaya komputasinya.

@container ?  {
  /* conditional styles */
}

Contoh terbaik yang saya lihat sejauh ini adalah menghapus huruf miring dari sesuatu seperti , , dan ketika mereka digunakan dalam konteks di mana konten sudah dicetak miring:

em, i, q {
  font-style: italic; /* default UA behavior */
}

/* When the container's font-style is italic, remove italics from these elements. */
@container style(font-style: italic) {
  em, i, q {
    font-style: normal;
  }
}

Itulah ide umumnya. Tetapi jika Anda tidak mengetahuinya, Miriam Suzanne, yang merupakan editor spesifikasi, membuat rangkaian yang berkelanjutan dan menyeluruh catatan pribadi tentang kueri gaya wadah yang tersedia untuk umum. Itu diperbarui beberapa hari yang lalu dan saya menghabiskan beberapa waktu di sana mencoba untuk memahami aspek-aspek yang lebih bernuansa dari kueri gaya. Ini hal yang tidak resmi, tapi saya pikir saya akan mencatat beberapa hal yang menonjol bagi saya. Siapa tahu? Mungkin itu hal yang akhirnya bisa kita nantikan!

Setiap elemen adalah wadah gaya

Kami bahkan tidak perlu menetapkan a container-name or container-type untuk menentukan wadah gaya karena semuanya adalah wadah gaya secara default.

Jadi, Anda melihat contoh di atas yang menghilangkan huruf miring? Perhatikan itu tidak mengidentifikasi wadah. Melompat langsung ke kueri menggunakan style() fungsi. Jadi, wadah apa yang ditanyakan? Ini akan menjadi induk langsung dari unsur-unsur tersebut menerima gaya yang diterapkan. Dan jika bukan itu, maka itu wadah relatif terdekat berikutnya yang diutamakan.

Aku suka itu. Ini sangat CSS-y untuk kueri untuk mencari kecocokan, lalu terus meluap hingga menemukan kondisi yang cocok.

Sulit bagi otak kecil saya untuk memahami mengapa kita bisa lolos dengan wadah implisit berdasarkan gaya, tetapi tidak terlalu banyak saat kita berurusan dengan kueri dimensional, seperti size dan inline-size. Miriam menjelaskannya dengan baik:

Kueri dimensi memerlukan css penahanan pada ukuran, tata letak, dan gaya wadah untuk mencegah pengulangan tata letak. Penahanan adalah hal yang invasif untuk diterapkan secara luas, jadi penting bagi penulis untuk memiliki kontrol yang hati-hati atas elemen apa yang merupakan (atau bukan) wadah ukuran.

Kueri berbasis gaya tidak memiliki batasan yang sama. Sudah tidak ada cara di CSS untuk gaya keturunan berdampak pada gaya yang dihitung dari ancestor. Jadi tidak diperlukan penahanan, dan tidak ada efek samping invasif atau tak terduga dalam menetapkan elemen sebagai a wadah kueri gaya.

(Tekankan milikku)

Semuanya bermuara pada konsekuensi - yang tidak ada sejauh semuanya menjadi wadah kueri gaya langsung dari kotak.

  • Jika wadah ditemukan: kondisi diselesaikan terhadap wadah itu.
  • Jika beberapa penampung cocok: penampung relatif terdekat akan diutamakan.
  • Jika tidak ada kecocokan yang ditemukan: unknown dikembalikan.

Itu sama saja semangat "memaafkan" sebagai sisa dari CSS.

Wadah dapat mendukung kueri dimensi dan gaya

Katakanlah kita ingin menentukan kueri gaya tanpa eksplisit container-name:

@container style(font-style: italic) {
  em {
    font-style: normal;
  }
}

Ini berhasil karena semua elemen adalah wadah gaya, tidak peduli container-type. Itulah yang memungkinkan kita untuk menanyakan gaya secara implisit dan mengandalkan kecocokan terdekat. Dan ini baik-baik saja karena, sekali lagi, tidak ada efek samping yang merugikan saat membuat wadah gaya.

Kita harus menggunakan eksplisit container-type untuk kueri dimensional, tetapi tidak terlalu banyak untuk kueri gaya karena setiap elemen adalah kueri gaya. Itu juga berarti wadah ini adalah gaya dan kueri dimensi:

.card-container {
  container: card / inline-size; /* implictly a style query container as well */
}

Mengecualikan penampung dari kueri

Mungkin kita tidak ingin wadah berpartisipasi dalam proses pencocokan. Di situlah mungkin untuk mengatur container-type: none pada sebuah elemen.

.some-element {
  container-type: none;
}

Kontainer kueri gaya eksplisit menawarkan lebih banyak kontrol atas apa yang ditanyakan

Misalnya, jika kita akan menulis kueri gaya untuk padding , tidak ada cara yang dapat diandalkan untuk menentukan penampung yang paling cocok, terlepas dari apakah kita bekerja dengan penampung yang diberi nama secara eksplisit atau induk langsung terdekat. Itu karena padding bukan merupakan harta warisan.

Jadi, dalam hal itu, kita harus menggunakan container-name untuk secara eksplisit memberi tahu browser dari wadah mana mereka dapat menarik. Kami bahkan dapat memberikan penampung beberapa nama eksplisit agar cocok dengan lebih banyak ketentuan:

.card {
  container-name: card layout theme;
}

Oh, dan container-name menerima sejumlah opsional dan dapat digunakan kembali nama untuk wadah! Itu bahkan lebih fleksibel ketika membantu browser membuat pilihan saat mencari kecocokan.

.theme {
  container-name: theme;
}
.grid {
  container-name: layout;
}
.card {
  container-name: card layout theme;
}

Saya agak bertanya-tanya apakah itu juga dapat dianggap sebagai "mundur" jika satu kontainer dilewati.

Kueri gaya dapat digabungkan

Grafik or dan and operator mengizinkan kami menggabungkan wueries untuk menjaga semuanya tetap KERING:

@container bubble style(--arrow-position: start start) or style(--arrow-position: end start) {
  .bubble::after {
    border-block-end-color: inherit;
    inset-block-end: 100%;
  }
}

/* is the same as... */
@container bubble style(--arrow-position: start start) {
  /* etc. */
}
@container bubble style(--arrow-position: end start) {
  /* etc. */
}

Beralih gaya

Ada sedikit tumpang tindih antara kueri gaya penampung dan pekerjaan yang dilakukan untuk mendefinisikan a toggle() fungsi. Misalnya, kita dapat menggilir dua font-style nilai, katakanlah italic dan normal:

em, i, q {
  font-style: italic;
}

@container style(font-style: italic) {
  em, i, q {
    font-style: normal;
  }
}

Dingin. Tetapi proposal untuk CSS Toggles menunjukkan bahwa toggle() function akan menjadi pendekatan yang lebih sederhana:

em, i, q {
  font-style: toggle(italic, normal);
}

Tapi apa pun di luar kasus penggunaan biner semacam ini ada di mana toggle() kurang cocok. Kueri gaya, bagaimanapun, bagus untuk digunakan. Miriam mengidentifikasi tiga contoh di mana kueri gaya lebih cocok daripada a toggle():

/* When font-style is italic, apply background color. */
/* Toggles can only handle one property at a time. */
@container style(font-style: italic) {
  em, i, q {
    background: lightpink;
  }
}

/* When font-style is italic and --color-mode equals light */
/* Toggles can only evaluate one condition at a time */
@container style((font-style: italic) and (--color-mode: light)) {
  em, i, q {
    background: lightpink;
  }
}

/* Apply the same query condition to multiple properties */
/* Toggles have to set each one individually as separate toggles */
@container style(font-style: italic) {
  em, i, q {
    /* clipped gradient text */
    background: var(--feature-gradient);
    background-clip: text;
    box-decoration-break: clone;
    color: transparent;
    text-shadow: none;
  }
}

Kueri gaya menyelesaikan "Peretasan Toggle Properti Kustom"

Perhatikan bahwa kueri gaya adalah solusi formal untuk “Trik pengalihan properti khusus CSS”. Di sana, kami menyetel properti kustom kosong (--foo: ;) dan gunakan metode fallback yang dipisahkan koma untuk "mengaktifkan dan menonaktifkan" properti saat properti kustom disetel ke nilai sebenarnya.

button {
  --is-raised: ; /* off by default */
  
  border: 1px solid var(--is-raised, rgb(0 0 0 / 0.1));
  box-shadow: var(
    --is-raised,
    0 1px hsl(0 0% 100% / 0.8) inset,
    0 0.1em 0.1em -0.1em rgb(0 0 0 / 0.2)
  );
  text-shadow: var(--is-raised, 0 -1px 1px rgb(0 0 0 / 0.3));
}

button:active {
  box-shadow: var(--is-raised, 0 1px 0.2em black inset);
}

#foo {
  --is-raised: initial; /* turned on, all fallbacks take effect. */
}

Itu sangat keren, juga banyak pekerjaan yang membuat kueri wadah gaya menjadi sepele.

Kueri gaya dan konten yang dihasilkan CSS

Untuk konten yang dihasilkan diproduksi oleh content properti dari ::before dan ::after elemen semu, penampung yang cocok adalah elemen tempat konten dihasilkan.

.bubble {
  --arrow-position: end end;
  container: bubble;
  border: medium solid green;
  position: relative;
}

.bubble::after {
  content: "";
  border: 1em solid transparent;
  position: absolute;
}

@container bubble style(--arrow-position: end end) {
  .bubble::after {
    border-block-start-color: inherit;
    inset-block-start: 100%;
    inset-inline-end: 1em;
  }
}

Kueri gaya dan komponen web

Kita dapat mendefinisikan komponen web sebagai wadah dan menanyakannya berdasarkan gaya. Pertama, kita memiliki dari komponen:


  
… …

Kemudian kita menggunakan :host pseudo-element sebagai wadah untuk mengatur a container-name, Sebuah container-type, dan beberapa atribut tingkat tinggi di atasnya:

:host {
  container: media-host / inline-size;
  --media-location: before;
  --media-style: square;
  --theme: light;
}

Elemen di dalam dapat meminta parameter dari elemen:

@container media-host style(--media-style: round) {
  [part='img'] {
    border-radius: 100%;
  }
}

Apa selanjutnya?

Sekali lagi, semua hal yang saya catat di sini didasarkan pada catatan Miriam, dan catatan itu bukan pengganti spesifikasi resmi. Tapi itu adalah indikasi dari apa yang sedang dibahas dan di mana hal-hal bisa mendarat di masa depan. Saya menghargai Miriam menghubungkan beberapa diskusi luar biasa yang masih berlangsung yang dapat kita ikuti untuk tetap menjadi yang teratas:

Stempel Waktu:

Lebih dari Trik CSS