스타일 쿼리 (@container style())를 사용하여 각 컨텍스트를 생성하거나 반응하는 항목을 하드코딩하지 않고도 컨텍스트 변형을 트리거합니다. 이렇게 하면 디자인 시스템 결합이 줄어들고 확장성과 구성요소 캡슐화가 개선됩니다.
예를 들어 section.featured { --surface: featured } 규칙은 컨텍스트를 표시할 수 있으며 방문 페이지도 main { --surface: featured }를 통해 기본값으로 설정될 수 있습니다. 그러면 구성요소는 --surface: featured에 반응하도록 선택합니다. 카드는 프로모션 배지를 표시하고 버튼은 기본적으로 채워진 변형으로 설정됩니다.
스타일 쿼리를 사용하면 양쪽이 분리된 상태를 유지할 수 있습니다. 추천 표시 경로에서는 이에 맞게 조정되는 요소의 이름을 지정하지 않으며 구성요소는 컨텍스트를 생성한 항목을 검사하지 않습니다. 새로운 구성요소, 새로운 추천 표시 경로 등 어느 쪽이든 다른 쪽에 영향을 주지 않고 독립적으로 확장할 수 있습니다. 하위 선택자 (예: .featured .button)는 반대 상황을 강제합니다. 선택자는 관계의 양쪽을 모두 인코딩해야 하며 어느 한쪽이 변경될 때마다 변경되어야 합니다.
이 가이드를 사용하는 경우
이 가이드에서는 동작 변경사항을 다룹니다. 즉, 배지 숨기기 또는 표시, 레이아웃 방향 전환, 버튼 변형 전환 등 컨텍스트에 따라 렌더링할 항목, 정렬 방법 또는 표시할 변형을 결정하는 구성요소를 다룹니다.
대신 토큰 수준 변경사항(밀도 모드, 테마 또는 여러 구성요소에서 패딩 및 색상과 같은 값을 균일하게 변경하는 기타 상위 토큰)이 필요한 경우 디자인 토큰 반응성을 참고하세요.
적절한 도구 선택
컨텍스트 관계의 양쪽이 독립적으로 변경될 수 있는 경우(새 요소가 컨텍스트를 생성하기 시작하거나 새 구성요소가 컨텍스트에 반응하기 시작할 수 있음) 스타일 쿼리를 사용합니다. 간접 참조는 확장성과 캡슐화에 대한 대가를 지불하며, 스타일 쿼리는 하위 선택자가 할 수 없는 섀도우 DOM 경계를 넘나듭니다. 이러한 유연성이 필요하지 않은 경우 더 간단한 도구를 사용하는 것이 좋습니다.
- 하위 요소 선택기 (
.toolbar .button): 재사용하거나 확장할 수 없는 고정된 일회성 관계입니다. YAGNI가 적용됩니다. 사용하지 않을 간접 참조를 추가하지 마세요. - 크기 쿼리 (
@container (min-width: …)): 시맨틱 상태가 아닌 사용 가능한 공간에 따라 레이아웃과 밀도가 변경됩니다. - 스타일 쿼리 (
@container style(…)): 시맨틱 상태 — 구성요소가 특정 컨텍스트에서 렌더링, 정렬 또는 표시해야 하는 항목입니다.
구현 지시문
- 컨테이너에서 CSS 맞춤 속성을 사용하여 시맨틱 컨텍스트 플래그를 정의합니다.
- 스타일 쿼리에
container-type를 설정하지 마세요. 스타일 쿼리는 가장 가까운 상위 요소에서 상속된 맞춤 속성을 쿼리하며 명시적인 포함 컨텍스트가 필요하지 않습니다. - 필수:
@container style(--property: value)를 사용하여 하위 요소에 조건부 스타일을 적용합니다. 스타일 쿼리는 속성이 설정된 요소와 일치할 수 없으며 하위 요소만 일치할 수 있습니다. - 관계가 확장 가능하거나 구성요소/섀도 DOM 경계를 넘나들어야 하는 경우 하위 선택자보다 스타일 쿼리를 사용하세요 (위의 적절한 도구 선택 참고). 하지만 간접 참조가 아무런 이점이 없는 고정된 일회성 관계의 경우 하위 선택자를 유지하세요.
구현 예시
/* 1. Set the context on a layout container */
.featured {
--surface: featured; /* Semantic context flag for children */
}
/* 2. Component reacts to inherited flag */
.button {
/* Default: Outlined informational style */
background: transparent;
border: 1px solid currentColor;
}
.badge {
/* Default: Hidden — only revealed in featured surfaces */
display: none;
}
@container style(--surface: featured) {
.button {
/* Automatic switch to Filled promotional style */
background: var(--brand-accent);
color: white;
border: none;
}
.badge {
/* Reveal decorative elements only in featured context */
display: block;
}
}
대체 전략
컨테이너 스타일 쿼리가 널리 사용될 때까지 점진적 개선으로 레이어링합니다. 어디서나 작동하는 선택기 기반 기본값을 제공하고 지원되는 경우 스타일 쿼리가 이를 재정의하도록 합니다. 컨텍스트 선택기에 :where()를 사용하면 스타일 쿼리 (동일한 특수성, 소스 순서에서 나중)가 자동으로 적용됩니다.
/* Default styles — work everywhere */
.button {
background: transparent;
border: 1px solid currentColor;
}
.badge {
display: none;
}
/* Selector-based contextual styles — broad browser support */
:where(.featured) .button {
background: var(--brand-accent);
color: white;
border: none;
}
:where(.featured) .badge {
display: block;
}
/* Progressive enhancement: style queries override when supported */
@container style(--surface: featured) {
.button {
background: var(--brand-accent);
color: white;
border: none;
}
.badge {
display: block;
}
}
선택기 대체는 문맥 스타일을 클래스 이름에 연결하여 구성요소를 DOM 배치에 결합합니다. 스타일 쿼리가 널리 지원되면 :where() 규칙을 삭제할 수 있습니다.