Applica il CSS in modo condizionale in base al supporto delle regole @

Funzionalità web: at-rule()

Utilizza @supports at-rule(@<at-rule name>) {…} per applicare in modo condizionale determinate regole o dichiarazioni CSS solo se una determinata regola at è supportata dal browser. Può contenere regole intere o essere utilizzata in combinazione con l'nidificazione CSS per applicare determinate dichiarazioni in modo condizionale.

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

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

NON utilizzare @supports at-rule() per applicare in modo condizionale la regola @ rilevata e nient'altro.

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

Rilevamento del supporto per le at-rule quando @supports at-rule() non è appropriato

Quando at-rule() non è un'opzione, a causa del supporto del browser o perché è necessario un rilevamento più approfondito, puoi utilizzare le indicazioni riportate di seguito.

Prova prima con proprietà, valori o selettori

@supports è già in grado di rilevare proprietà, valori e selettori (tramite @supports selector(...)). In molti casi, puoi utilizzarli per rilevare il supporto di una funzionalità senza dover controllare la regola @ stessa.

Ad esempio, anziché @supports at-rule(@function) per rilevare i supporti per le funzioni personalizzate, puoi utilizzare @supports (color: --foo()).

In altri casi, potrebbero essere presenti pseudo-classi o pseudo-elementi disponibili solo quando è supportata una determinata regola at, che può essere utilizzata per rilevare il supporto.

Rilevamento dei tipi di query container

at-rule() consente SOLO il rilevamento di at-rule per nome. NON consente il rilevamento di altre sintassi o descrittori. Ad esempio, questo non funzionerà:

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

Per molti tipi di query container, puoi utilizzare container-type con un valore appropriato. Ad esempio, @supports (container-type: scroll-state) per le query sullo stato di scorrimento o @supports (container-type: size)container-type: anchoredforanchored()`.

Tuttavia, non esiste un container-type per le query di stile. IMPORTANTE: NON provare a utilizzare @supports (container-type: style) per rilevare il supporto delle query di stile, perché non funzionerà.

Puoi invece provare una query di stile che è sempre vera:

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

La corrispondenza verrà trovata in qualsiasi browser che supporti le query di stile, indipendentemente dal nome o dal valore della proprietà utilizzato, a condizione che siano uguali in entrambi.

Proprietà personalizzate registrate (@property)

In alcuni casi, se il CSS condizionale da applicare può essere ridotto a una singola proprietà, puoi utilizzare una proprietà personalizzata dedicata registrata a questo scopo:

/* 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, );
}

Per una soluzione per uso generico, puoi registrare una proprietà non ereditata e impostarla su (uno spazio) nell'elemento 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);
}

Note:

  • Entrambe le opzioni funzionano solo se lo spazio vuoto è un'alternativa accettabile. In altri casi, dovrai utilizzare JS come descritto di seguito.
  • La soluzione per uso generico dipende dalla non ereditarietà, quindi non funzionerà per le dichiarazioni sull'elemento root.

Utilizzo di JavaScript come ultima risorsa

Per intere regole @, verifica la presenza di determinate interfacce in JavaScript. Ad esempio, se è definito globalThis.CSSFunctionRule, @function è supportato.

Se devi eseguire test più approfonditi (ad es. per determinati preludi, regole nidificate, descrittori), puoi configurare un test e verificare come è stato analizzato:

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

IMPORTANTE:

  • Quando utilizzi JS per rilevare il supporto delle funzionalità CSS, NON applicare gli stili direttamente da JS. Applica invece una classe all'elemento root e crea una ramificazione nel CSS.
  • Tieni presente che le query container vengono analizzate anche se il preludio non viene riconosciuto e non è possibile rilevare il supporto di determinati tipi di query container dalla struttura CSSOM.
  • NON utilizzare CSS.registerProperty per rilevare il supporto di @property, poiché il suo supporto è leggermente più ampio.

Strategie di riserva

A meno che non rientri nel tuo target di supporto, utilizza SOLO @supports (at-rule()) per rilevare le regole @ per le quali il supporto è più limitato rispetto alla funzionalità @supports (at-rule()) stessa.

Per applicare in modo condizionale il CSS in base al supporto delle at-rule rilasciate prima di questa funzionalità, utilizza le indicazioni riportate nella sezione precedente.

Per rilevare il supporto della funzionalità @supports at-rule() stessa, puoi utilizzare una regola at che è garantito che esista in tutti i browser che supportano @supports at-rule(), ad esempio @supports at-rule(@media) { ... }.