CSS voorwaardelijk toepassen op basis van ondersteuning voor at-regels

Webfuncties: at-rule()

Gebruik @supports at-rule(@<at-rule name>) {…} om bepaalde CSS-regels of -declaraties alleen voorwaardelijk toe te passen als een bepaalde at-regel wordt ondersteund door de browser. Deze kan hele regels bevatten of worden gebruikt in combinatie met CSS-nesting om bepaalde declaraties voorwaardelijk toe te passen.

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

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

Gebruik @supports at-rule() NIET om de at-regel die wordt gevonden voorwaardelijk toe te passen en niets anders.

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

Ondersteuning voor at-regels detecteren als @supports at-rule() niet geschikt is

Als at-rule() geen optie is, vanwege browserondersteuning of omdat er diepere detectie nodig is, kunt u de onderstaande richtlijnen gebruiken.

Probeer eerst eigenschappen, waarden of kiezers

@supports kan al property's, waarden en selectors detecteren (via @supports selector(...)). In veel gevallen kun je deze gebruiken om ondersteuning voor een functie te detecteren zonder dat je de at-regel zelf hoeft te controleren.

In plaats van @supports at-rule(@function) om ondersteuning voor aangepaste functies te detecteren, kun je bijvoorbeeld @supports (color: --foo()) gebruiken.

In andere gevallen zijn er misschien pseudoklassen of pseudoelementen die alleen beschikbaar zijn als een bepaalde at-regel wordt ondersteund. Deze kunnen worden gebruikt om ondersteuning te detecteren.

Typen containerquery's detecteren

at-rule() staat alleen detectie van at-regels toe op naam. De functie staat GEEN detectie van andere syntaxis of beschrijvingen toe. Dit werkt bijvoorbeeld niet:

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

Voor veel typen containerquery's kun je container-type gebruiken met een geschikte waarde. Bijvoorbeeld @supports (container-type: scroll-state) voor scroll-state-query's of @supports (container-type: size)container-type: anchoredforanchored()'s.

Er is geen container-type voor stijlquery's. BELANGRIJK: Probeer @supports (container-type: style) NIET te gebruiken om ondersteuning voor stijlquery's te detecteren, omdat dit niet werkt.

In plaats daarvan kun je een stijlquery proberen die altijd waar is:

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

Dit komt overeen in elke browser die stijlquery's ondersteunt, ongeacht de propertynaam of -waarde die je gebruikt, mits deze in beide hetzelfde zijn.

Geregistreerde aangepaste eigenschappen (@property)

In sommige gevallen, als de voorwaardelijke CSS die moet worden toegepast, kan worden teruggebracht tot één eigenschap, kun je een speciale aangepaste eigenschap gebruiken die voor dit doel is geregistreerd:

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

Voor een meer algemene oplossing kun je een niet-overervende property registreren en deze instellen op (een spatie) voor het hoofdelement:

{# 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);
}

Opmerkingen:

  • Beide werken alleen als witruimte een acceptabel alternatief is. In andere gevallen moet u JS gebruiken, zoals hieronder beschreven.
  • De algemene oplossing is afhankelijk van niet-overerving, dus deze werkt niet voor declaraties voor het hoofdelement.

JavaScript gebruiken als laatste redmiddel

Voor hele at-regels check je of bepaalde interfaces aanwezig zijn in JavaScript. Als globalThis.CSSFunctionRule bijvoorbeeld is gedefinieerd, wordt @function ondersteund.

Als je dieper wilt testen (bijvoorbeeld voor bepaalde preludes, geneste regels, descriptors), kun je een test instellen en controleren hoe deze is geparseerd:

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

BELANGRIJK:

  • Als je JS gebruikt om ondersteuning voor CSS-functies te detecteren, pas je de stijlen van JS NIET rechtstreeks toe. Pas in plaats daarvan een klasse toe op het hoofdelement en vertak daarvan in CSS.
  • Houd er rekening mee dat containerquery's worden geparseerd, zelfs als de prelude niet wordt herkend. Er is geen manier om ondersteuning voor bepaalde typen containerquery's te detecteren vanuit de CSSOM-structuur.
  • Gebruik CSS.registerProperty NIET om ondersteuning voor @property te detecteren, omdat de ondersteuning hiervoor iets breder is.

Reservestrategieën

Tenzij dit binnen je supportdoel valt, gebruik je ALLEEN @supports (at-rule()) om at-regels te detecteren waarvoor de support beperkter is dan de functie @supports (at-rule()) zelf.

Als je CSS voorwaardelijk wilt toepassen op basis van ondersteuning voor at-regels die vóór deze functie zijn uitgebracht, gebruik je de richtlijnen in het gedeelte hierboven.

Als je wilt detecteren of de functie @supports at-rule() zelf wordt ondersteund, kun je een at-regel gebruiken die gegarandeerd bestaat in alle browsers die @supports at-rule() ondersteunen, zoals @supports at-rule(@media) { ... }.