Menerapkan CSS Berdasarkan Kondisi Dukungan At-Rule

Fitur web: at-rule()

Gunakan @supports at-rule(@<at-rule name>) {…} untuk menerapkan aturan atau deklarasi CSS tertentu secara bersyarat hanya jika aturan-at tertentu didukung oleh browser. Aturan ini dapat berisi seluruh aturan, atau digunakan bersama dengan penyusunan bertingkat CSS untuk menerapkan deklarasi tertentu secara bersyarat.

.foo {
  background: var(--accent-color);

  @supports at-rule(@property) {
    background-image: var(--rainbow-gradient);
    animation: sliding-rainbow 1s linear infinite;
  }
}

JANGAN gunakan @supports at-rule() untuk menerapkan aturan-at secara bersyarat yang sedang dideteksi dan tidak ada yang lain.

/* BAD: CSS already ignores rules the browser doesn't understand, so this is unnecessary */
@supports at-rule(@starting-style) {
  @starting-style {
    /* ... */
  }
}

Mendeteksi dukungan untuk aturan-at saat @supports at-rule() tidak sesuai

Jika at-rule() tidak dapat digunakan, baik karena dukungan browser atau karena diperlukan deteksi yang lebih mendalam, Anda dapat menggunakan panduan di bawah.

Coba properti, nilai, atau pemilih terlebih dahulu

@supports sudah dapat mendeteksi properti, nilai, dan pemilih (melalui @supports selector(...)). Dalam banyak kasus, Anda dapat menggunakannya untuk mendeteksi dukungan fitur tanpa perlu memeriksa aturan at-rule itu sendiri.

Misalnya, Anda dapat menggunakan @supports (color: --foo()), bukan @supports at-rule(@function), untuk mendeteksi dukungan fungsi kustom.

Dalam kasus lain, mungkin ada pseudo-class atau pseudo-element yang hanya tersedia jika aturan-at tertentu didukung, yang dapat digunakan untuk mendeteksi dukungan.

Mendeteksi jenis kueri penampung

at-rule() HANYA mengizinkan deteksi at-rule berdasarkan nama. Aturan ini TIDAK mengizinkan deteksi sintaksis atau deskriptor lain. Misalnya, hal berikut tidak akan berfungsi:

@supports at-rule(@container style(--a: 1)) {
  /* ... */
}

Untuk berbagai jenis kueri penampung, Anda dapat menggunakan container-type dengan nilai yang sesuai. Misalnya, @supports (container-type: scroll-state) untuk kueri status scroll atau kueri @supports (container-type: size)container-type: anchoredforanchored()`.

Namun, tidak ada container-type untuk kueri gaya. PENTING: JANGAN mencoba @supports (container-type: style) untuk mendeteksi dukungan kueri gaya, karena ini tidak akan berfungsi.

Sebagai gantinya, Anda dapat mencoba kueri gaya yang selalu benar:

@container style(--a: 1) or (not (style(--a: 1))) {
  /* Rules here will only be applied if style queries are supported */
}

Kueri ini akan cocok di browser apa pun yang mendukung kueri gaya, terlepas dari nama atau nilai properti yang Anda gunakan, asalkan keduanya sama.

Properti kustom terdaftar (@property)

Dalam beberapa kasus, jika CSS bersyarat yang akan diterapkan dapat dikurangi menjadi satu properti, Anda dapat menggunakan properti kustom khusus yang didaftarkan untuk tujuan ini:

/* Use a custom property to conditionally include the dash animation */
@property --progress-dash-animation {
  syntax: "*";
  inherits: false;
  initial-value: , progress-dash 3s ease-in-out infinite;
}

.spinner {
  /* The dash animation is only included if @property is supported */
  animation:
    progress-spin var(--_used-spinner-duration) linear infinite
    var(--progress-dash-animation, );
}

Untuk solusi yang lebih umum, Anda dapat mendaftarkan properti yang tidak diwariskan dan menetapkannya ke (spasi) pada elemen root:

{# Testcase: https://codepen.io/leaverou/pen/KwWzpVr #}

@property --supports-atproperty {
    syntax: "*";
    inherits: false;
}

:root {
    --supports-atproperty: ;
}

body {
  /* The background is only applied if @property is supported */
    background: var(--supports-atproperty, green);
}

Catatan:

  • Kedua opsi ini hanya berfungsi jika spasi kosong adalah alternatif yang dapat diterima. Untuk kasus lainnya, Anda harus menggunakan JS seperti yang dijelaskan di bawah.
  • Solusi tujuan umum bergantung pada non-pewarisan, sehingga tidak akan berfungsi untuk deklarasi pada elemen root.

Menggunakan JavaScript sebagai upaya terakhir

Untuk seluruh aturan-at, periksa keberadaan antarmuka tertentu di JavaScript. Misalnya, jika globalThis.CSSFunctionRule ditentukan, @function akan didukung.

Jika perlu menguji lebih dalam (misalnya, untuk prelude tertentu, aturan bertingkat, deskriptor), Anda dapat menyiapkan pengujian dan memeriksa cara penguraiannya:

const sheet = new CSSStyleSheet();
sheet.replaceSync(`
  @page {
    @top-left {
      content: "test";
    }
  }
`);
const SUPPORTS_PAGE_MARGINS = Boolean(sheet.cssRules[0]?.cssRules?.[0]);

PENTING:

  • Saat menggunakan JS untuk mendeteksi dukungan fitur CSS, JANGAN menerapkan gaya dari JS secara langsung. Sebagai gantinya, terapkan class ke elemen root dan buat cabang dari elemen tersebut di CSS.
  • Perhatikan bahwa kueri penampung diuraikan meskipun prelude tidak dikenali, dan tidak ada cara untuk mendeteksi dukungan untuk jenis kueri penampung tertentu dari struktur CSSOM.
  • JANGAN gunakan CSS.registerProperty untuk mendeteksi dukungan untuk @property karena dukungannya sedikit lebih luas.

Strategi penggantian

Kecuali jika ini termasuk dalam target dukungan Anda, HANYA gunakan @supports (at-rule()) untuk mendeteksi aturan-at yang dukungannya lebih sempit daripada fitur @supports (at-rule()) itu sendiri.

Untuk menerapkan CSS secara bersyarat berdasarkan dukungan untuk aturan at yang dikirim sebelum fitur ini, gunakan panduan di bagian di atas.

Untuk mendeteksi dukungan untuk fitur @supports at-rule() itu sendiri, Anda dapat menggunakan aturan-at yang dijamin ada di semua browser yang mendukung @supports at-rule(), seperti @supports at-rule(@media) { ... }.