CSS basierend auf der Unterstützung von At-Regeln bedingt anwenden

Webfunktionen: at-rule()

Mit @supports at-rule(@<at-rule name>) {…} können Sie bestimmte CSS-Regeln oder -Deklarationen nur dann bedingt anwenden, wenn eine bestimmte At-Regel vom Browser unterstützt wird. Sie kann ganze Regeln enthalten oder in Verbindung mit CSS-Verschachtelung verwendet werden, um bestimmte Deklarationen bedingt anzuwenden.

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

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

Verwenden Sie @supports at-rule() NICHT, um die erkannte At-Regel bedingt anzuwenden und sonst nichts.

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

Unterstützung für At-Regeln erkennen, wenn @supports at-rule() nicht geeignet ist

Wenn at-rule() aufgrund der Browserunterstützung oder weil eine genauere Erkennung erforderlich ist, nicht verwendet werden kann, können Sie die folgenden Hinweise nutzen.

Zuerst Attribute, Werte oder Selektoren ausprobieren

@supports kann bereits Attribute, Werte und Selektoren (über @supports selector(...)) erkennen. In vielen Fällen können Sie damit die Unterstützung für eine Funktion erkennen, ohne die At-Regel selbst prüfen zu müssen.

Anstelle von @supports at-rule(@function) können Sie beispielsweise @supports (color: --foo()) verwenden, um die Unterstützung für benutzerdefinierte Funktionen zu erkennen.

In anderen Fällen gibt es möglicherweise Pseudoklassen oder Pseudoelemente, die nur verfügbar sind, wenn eine bestimmte At-Regel unterstützt wird. Diese können verwendet werden, um die Unterstützung zu erkennen.

Containertypen für Abfragen erkennen

at-rule() erlaubt NUR die Erkennung von At-Regeln nach Name. Andere Syntax oder Deskriptoren können damit NICHT erkannt werden. Beispiel (funktioniert nicht):

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

Für viele Arten von Containerabfragen können Sie container-type mit einem geeigneten Wert verwenden. Beispiel: @supports (container-type: scroll-state) für Scrollstatus-Abfragen oder @supports (container-type: size)container-type: anchoredforanchored()`-Abfragen.

Für Stilabfragen gibt es jedoch kein container-type. WICHTIG: Versuchen Sie NICHT, @supports (container-type: style) zu verwenden, um die Unterstützung für Stilabfragen zu erkennen, da dies nicht funktioniert.

Stattdessen können Sie eine Stilabfrage verwenden, die immer „true“ ist:

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

Dies funktioniert in jedem Browser, der Stilabfragen unterstützt, unabhängig davon, welchen Attributnamen oder -wert Sie verwenden, sofern beide übereinstimmen.

Registrierte benutzerdefinierte Eigenschaften (@property)

Wenn das anzuwendende bedingte CSS auf eine einzelne Eigenschaft reduziert werden kann, können Sie in einigen Fällen eine dedizierte benutzerdefinierte Eigenschaft verwenden, die für diesen Zweck registriert wurde:

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

Für eine Lösung für allgemeine Zwecke können Sie eine nicht vererbende Property registrieren und sie für das Stammelement auf (ein Leerzeichen) festlegen:

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

Hinweise:

  • Beide funktionieren nur, wenn Leerzeichen eine akzeptable Alternative sind. In anderen Fällen müssen Sie JS wie unten beschrieben verwenden.
  • Die Lösung für allgemeine Zwecke basiert auf der Nichtvererbung und funktioniert daher nicht für Deklarationen im Stammelement.

JavaScript als letzte Option verwenden

Bei ganzen At-Regeln können Sie prüfen, ob bestimmte Schnittstellen in JavaScript vorhanden sind. Wenn beispielsweise globalThis.CSSFunctionRule definiert ist, wird @function unterstützt.

Wenn Sie genauer testen möchten (z.B. für bestimmte Preludes, verschachtelte Regeln, Deskriptoren), können Sie einen Test einrichten und prüfen, wie er geparst wurde:

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

WICHTIG:

  • Wenn Sie die Unterstützung von CSS-Funktionen mit JS erkennen, wenden Sie die Stile NICHT direkt über JS an. Wenden Sie stattdessen eine Klasse auf das Stammelement an und verzweigen Sie in CSS davon.
  • Beachten Sie, dass Containerabfragen auch dann geparst werden, wenn die Einleitung nicht erkannt wird. Es gibt keine Möglichkeit, die Unterstützung für bestimmte Arten von Containerabfragen aus der CSSOM-Struktur zu erkennen.
  • Verwenden Sie NICHT CSS.registerProperty, um die Unterstützung für @property zu ermitteln, da die Unterstützung etwas breiter ist.

Fallback-Strategien

Wenn dies nicht innerhalb Ihres Supportziels liegt, verwenden Sie @supports (at-rule()) NUR, um At-Regeln zu erkennen, für die der Support eingeschränkter ist als für das Feature @supports (at-rule()) selbst.

Wenn Sie CSS bedingt anwenden möchten, basierend auf der Unterstützung von At-Regeln, die vor dieser Funktion eingeführt wurden, verwenden Sie die Anleitung im Abschnitt oben.

Um die Unterstützung für die @supports at-rule()-Funktion selbst zu erkennen, können Sie eine At-Regel verwenden, die garantiert in allen Browsern vorhanden ist, die @supports at-rule() unterstützen, z. B. @supports at-rule(@media) { ... }.