Warunkowe stosowanie CSS na podstawie obsługi reguł at-rule

Funkcje internetowe: at-rule()

Użyj @supports at-rule(@<at-rule name>) {…}, aby warunkowo stosować określone reguły lub deklaracje CSS tylko wtedy, gdy przeglądarka obsługuje określoną regułę at. Może zawierać całe reguły lub być używana w połączeniu z zagnieżdżaniem CSS, aby warunkowo stosować określone deklaracje.

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

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

NIE używaj @supports at-rule() do warunkowego stosowania wykrywanej reguły at-rule i niczego innego.

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

Wykrywanie obsługi reguł at, gdy @supports at-rule() nie jest odpowiednie

Jeśli nie możesz użyć at-rule(), ponieważ przeglądarka nie obsługuje tej funkcji lub potrzebujesz bardziej szczegółowego wykrywania, skorzystaj z poniższych wskazówek.

Najpierw wypróbuj właściwości, wartości lub selektory

@supports może już wykrywać właściwości, wartości i selektory (za pomocą @supports selector(...)). W wielu przypadkach możesz ich używać do wykrywania obsługi funkcji bez konieczności sprawdzania samej reguły at.

Na przykład zamiast @supports at-rule(@function) do wykrywania obsługi funkcji niestandardowych możesz użyć @supports (color: --foo()).

W innych przypadkach mogą występować pseudoklasy lub pseudoelementy, które są dostępne tylko wtedy, gdy obsługiwana jest określona reguła at-rule, co może służyć do wykrywania obsługi.

Wykrywanie typów zapytań dotyczących kontenerów

at-rule() umożliwia wykrywanie reguł @ tylko według nazwy. NIE umożliwia wykrywania innych składni ani deskryptorów. Na przykład to nie zadziała:

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

W przypadku wielu typów zapytań o kontener możesz użyć właściwości container-type z odpowiednią wartością. Na przykład @supports (container-type: scroll-state) w przypadku zapytań o stan przewijania lub @supports (container-type: size)container-type: anchoredforanchored()`.

Nie ma jednak funkcji container-type w przypadku zapytań o styl. WAŻNE: NIE próbuj używać @supports (container-type: style) do wykrywania obsługi zapytań o style, ponieważ to nie zadziała.

Zamiast tego możesz użyć zapytania o styl, które zawsze jest prawdziwe:

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

Będzie to pasować w każdej przeglądarce, która obsługuje zapytania o style, niezależnie od używanej nazwy lub wartości właściwości, pod warunkiem, że są one takie same w obu przypadkach.

Zarejestrowane właściwości niestandardowe (@property)

W niektórych przypadkach, jeśli warunkowy kod CSS, który ma zostać zastosowany, można ograniczyć do jednej właściwości, możesz użyć specjalnej właściwości niestandardowej zarejestrowanej w tym celu:

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

W rozwiązaniu do zwykłych obciążeń możesz zarejestrować właściwość niedziedziczoną i ustawić ją na (spacja) w elemencie głównym:

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

Uwagi:

  • Obie te opcje działają tylko wtedy, gdy odstęp jest akceptowalną alternatywą. W innych przypadkach musisz użyć kodu JS, jak opisano poniżej.
  • Rozwiązanie do zwykłych obciążeń zależy od braku dziedziczenia, więc nie będzie działać w przypadku deklaracji w elemencie głównym.

Używanie JavaScriptu w ostateczności

W przypadku całych reguł at-rule sprawdź, czy w kodzie JavaScript występują określone interfejsy. Jeśli na przykład zdefiniowano globalThis.CSSFunctionRule, obsługiwany jest @function.

Jeśli chcesz przeprowadzić bardziej szczegółowe testy (np. dotyczące określonych wstępów, reguł zagnieżdżonych, deskryptorów), możesz skonfigurować test i sprawdzić, jak został przeanalizowany:

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

WAŻNE:

  • Jeśli używasz JS do wykrywania obsługi funkcji CSS, NIE stosuj stylów bezpośrednio z JS. Zamiast tego zastosuj klasę do elementu głównego i utwórz odgałęzienie w kodzie CSS.
  • Pamiętaj, że zapytania o kontener są analizowane nawet wtedy, gdy wstęp nie jest rozpoznawany, i nie ma możliwości wykrycia obsługi niektórych typów zapytań o kontener ze struktury CSSOM.
  • NIE używaj CSS.registerProperty do wykrywania obsługi @property, ponieważ jej obsługa jest nieco szersza.

Strategie zastępcze

Jeśli nie jest to objęte Twoim celem pomocy, używaj @supports (at-rule()) TYLKO do wykrywania reguł at, w przypadku których pomoc jest węższa niż sama funkcja @supports (at-rule()).

Aby warunkowo stosować CSS na podstawie obsługi reguł at-rules, które zostały wprowadzone przed tą funkcją, skorzystaj ze wskazówek w sekcji powyżej.

Aby wykryć obsługę samej funkcji @supports at-rule(), możesz użyć reguły at-rule, która na pewno istnieje we wszystkich przeglądarkach obsługujących @supports at-rule(), np. @supports at-rule(@media) { ... }.