At-Rule 지원에 따라 조건부로 CSS 적용

웹 기능: at-rule()

@supports at-rule(@<at-rule name>) {…}를 사용하여 브라우저에서 특정 at-rule을 지원하는 경우에만 특정 CSS 규칙 또는 선언을 조건부로 적용합니다. 여기에는 전체 규칙이 포함되거나 CSS 중첩과 함께 사용하여 특정 선언을 조건부로 적용할 수 있습니다.

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

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

@supports at-rule()를 사용하여 감지되는 at 규칙만 조건부로 적용하지 마세요.

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

@supports at-rule()가 적절하지 않은 경우 at 규칙 지원 감지

브라우저 지원 또는 더 심층적인 감지가 필요하여 at-rule()를 사용할 수 없는 경우 아래 안내를 따르세요.

속성, 값 또는 선택기를 먼저 사용해 보세요.

@supports는 이미 속성, 값, 선택기를 감지할 수 있습니다(@supports selector(...)를 통해). 대부분의 경우 이를 사용하여 at-규칙 자체를 확인하지 않고도 기능 지원을 감지할 수 있습니다.

예를 들어 커스텀 함수 지원을 감지하기 위해 @supports at-rule(@function) 대신 @supports (color: --foo())를 사용할 수 있습니다.

다른 경우에는 특정 at-규칙이 지원되는 경우에만 사용할 수 있는 의사 클래스 또는 의사 요소가 있을 수 있으며, 이를 사용하여 지원을 감지할 수 있습니다.

컨테이너 쿼리 유형 감지

at-rule()는 이름으로만 at-규칙을 감지할 수 있습니다. 다른 문법이나 설명어는 감지할 수 없습니다. 예를 들어 다음은 작동하지 않습니다.

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

다양한 유형의 컨테이너 쿼리에 적절한 값과 함께 container-type를 사용할 수 있습니다. 예: 스크롤 상태 쿼리의 경우 @supports (container-type: scroll-state), @supports (container-type: size)container-type: anchoredforanchored()` 쿼리.

하지만 스타일 쿼리에는 container-type가 없습니다. 중요: 스타일 쿼리 지원을 감지하기 위해 @supports (container-type: style)를 시도하지 마세요. 작동하지 않습니다.

대신 항상 참인 스타일 쿼리를 사용해 볼 수 있습니다.

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

이는 사용 중인 속성 이름이나 값에 관계없이 스타일 쿼리를 지원하는 모든 브라우저에서 일치합니다(두 브라우저에서 동일한 경우).

등록된 맞춤 속성 (@property)

경우에 따라 적용할 조건부 CSS를 단일 속성으로 줄일 수 있다면 이 목적으로 등록된 전용 맞춤 속성을 사용할 수 있습니다.

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

더 범용적인 솔루션을 사용하려면 상속되지 않는 속성을 등록하고 루트 요소에서 (공백)로 설정하면 됩니다.

{# 테스트 사례: 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);
}

참고:

  • 두 가지 모두 공백이 허용되는 대안인 경우에만 작동합니다. 그 외의 경우에는 아래 설명에 따라 JS를 사용해야 합니다.
  • 범용 솔루션은 비상속에 의존하므로 루트 요소의 선언에는 작동하지 않습니다.

최후의 수단으로 JavaScript 사용

전체 규칙의 경우 JavaScript에 특정 인터페이스가 있는지 확인합니다. 예를 들어 globalThis.CSSFunctionRule가 정의된 경우 @function가 지원됩니다.

특정 서문, 중첩된 규칙, 설명자 등 더 심층적인 테스트가 필요한 경우 테스트를 설정하고 파싱 방식을 확인할 수 있습니다.

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

중요:

  • JS를 사용하여 CSS 기능 지원을 감지할 때는 JS에서 직접 스타일을 적용하지 마세요. 대신 루트 요소에 클래스를 적용하고 CSS에서 분기합니다.
  • 프렐류드가 인식되지 않더라도 컨테이너 쿼리가 파싱되며 CSSOM 구조에서 특정 유형의 컨테이너 쿼리에 대한 지원을 감지할 방법이 없습니다.
  • CSS.registerProperty를 사용하여 @property 지원을 감지하지 마세요. 지원 범위가 약간 더 넓기 때문입니다.

대체 전략

지원 대상에 포함되지 않는 한 @supports (at-rule()) 기능 자체보다 지원 범위가 좁은 at-규칙을 감지하는 데 @supports (at-rule())만 사용하세요.

이 기능 이전에 제공된 at-규칙 지원을 기반으로 CSS를 조건부로 적용하려면 위 섹션의 안내를 참고하세요.

@supports at-rule() 기능 자체에 대한 지원을 감지하려면 @supports at-rule()를 지원하는 모든 브라우저에 존재하도록 보장되는 at-rule(예: @supports at-rule(@media) { ... })을 사용할 수 있습니다.