안녕하세요! 오늘 함께 살펴볼 내용은 앞서 배운 컨테이너 쿼리를 한 단계 더 깊이 파고드는 컨테이너 크기 및 스타일 쿼리 사용하기(Using container size and style queries)입니다.
크기 기반의 반응형 디자인을 넘어, 부모 컨테이너가 가진 '스타일' 값(특히 커스텀 속성, 일명 CSS 변수)에 따라 자식 컴포넌트의 디자인을 완전히 바꿀 수 있는 아주 강력한 기능이랍니다. 테마(Theme)를 관리하거나 재사용성이 높은 컴포넌트를 만들 때 정말 유용하게 쓰일 수 있습니다. 그럼 MDN 문서를 통해 자세히 알아볼까요?
컨테이너 쿼리(Container queries)를 사용하면 특정 컨테이너 안에 중첩된 요소들에게 해당 컨테이너의 특징(크기, 스타일 등)을 기반으로 스타일을 적용할 수 있습니다. 쿼리(조건문)는 컨테이너가 해당 조건을 만족하는지에 따라 참(true) 또는 거짓(false)을 반환합니다.
컨테이너 쿼리는 미디어 쿼리(media queries)와 매우 유사합니다. @media @규칙이 뷰포트(화면) 크기나 기기의 특성에 따라 스타일을 적용하게 해준다면, @container @규칙은 뷰포트가 아닌 부모 컨테이너 요소의 크기나 다른 스타일 특징에 따라 스타일을 적용하게 해줍니다. 컨테이너 쿼리는 미디어 쿼리와 똑같은 구문 규칙과 논리 연산자(and, or, not 등)를 사용합니다.
@container <container-condition># {
/* <stylesheet> */
}
컨테이너 쿼리에는 세 가지 유형이 있습니다:
컨테이너 크기 쿼리 (Container size queries)크기 쿼리는 컨테이너 요소의 현재 크기(size)(방향 및 종횡비(aspect ratio) 포함)를 기준으로 요소에 스타일을 적용할 수 있게 해줍니다. 이 기능을 사용하려면 요소를 명시적으로 크기 쿼리 컨테이너(size query containers)로 선언해야 합니다.
컨테이너 스타일 쿼리 (Container style queries)스타일 쿼리는 컨테이너 요소의 '스타일 특징'을 기준으로 요소에 스타일을 적용할 수 있게 해줍니다. 비어 있지 않은 모든 요소는 스타일 쿼리 컨테이너가 될 수 있습니다. 스타일 특징이란 CSS 속성, CSS 커스텀 속성(custom property, CSS 변수), 또는 유효한 CSS 선언(declaration)이 될 수 있습니다.
이를 통해 컨테이너가 display: inline-flex 선언을 가지고 있는지, 혹은 특정 커스텀 속성값이 무엇인지에 따라 자손 요소들에게 각기 다른 스타일을 적용할 수 있습니다.
스크롤 상태 쿼리를 사용하면 쿼리 대상 요소가 부분적으로 스크롤되었는지, 또는 컨테이너가 스크롤 스냅(scroll snap) 컨테이너에 맞춰 스냅되었는지 등 스크롤 상태 조건에 따라 컨테이너의 자손들에게 선택적으로 CSS 규칙을 적용할 수 있습니다. 이 기능을 사용하려면 요소를 명시적으로 스크롤 상태 쿼리 컨테이너(scroll-state query containers)로 선언해야 합니다.
이 가이드에서는 다음 세 가지를 중심으로 컨테이너 쿼리의 기초를 배웁니다:
@container @규칙의 <container-condition> 내에서 style() 함수 표기법을 사용하여 커스텀 속성을 이용한 스타일 쿼리 (style queries with custom properties) 작성하기스크롤 상태 쿼리에 대해서는 컨테이너 스크롤 상태 쿼리 사용하기 가이드에서 별도로 다룹니다.
컨테이너 크기 쿼리는 '크기 조건'으로 필터링됩니다. 특정 요소가 컨테이너로 선언되어 있고, 그 요소에 대한 컨테이너 조건이 참(true)일 경우 관련된 스타일이 내부 요소들에 적용됩니다. 기준이 되는 '크기 컨테이너'는 격리(containment) 문맥이 설정된 가장 가까운 조상 요소가 됩니다.
요소를 크기 쿼리 컨테이너로 선언하려면 container-type 속성 (또는 container 단축 속성)을 size 또는 inline-size로 설정해야 합니다.
@container (orientation: landscape) {
/* 가로 모드일 때 이 크기 컨테이너의 자손들에게 적용될 스타일 */
}
.sizeContainer {
container-type: size;
}
크기 쿼리 컨테이너를 선언하면 해당 요소에 격리(containment) 특성이 추가됩니다. 이것은 성능상 필수적인 조치입니다. 브라우저가 화면에 있는 모든 DOM 요소의 크기를 시도 때도 없이 계속 조회한다면 성능과 사용자 경험에 끔찍한 결과를 초래할 테니까요. 게다가, 자식 요소의 스타일 변화가 부모 컨테이너의 크기를 변화시킨다면 무한 루프에 빠질 위험도 있습니다.
컨테이너 크기 쿼리에서 <container-condition>은 하나 이상의 <size-query>를 포함합니다. 각각의 크기 쿼리는 크기 특성 이름, 비교 연산자(>, < 등), 그리고 값으로 구성됩니다. 조회할 수 있는 크기 특성은 width, height, inline-size, block-size, aspect-ratio, 그리고 orientation으로 제한됩니다. 여러 개의 <size-query>를 결합하는 문법과 논리 연산은 @media 미디어 쿼리와 동일합니다.
form {
container-type: inline-size;
}
@container (10em <= width <= 20em) {
/* styles */
}
이 예제에서 <container-condition>은 (10em <= width <= 20em)이라는 단일 <size-query>를 포함하고 있습니다. 이 경우, 컨테이너 타입이 선언된 모든 <form> 요소는 이름이 지정되지 않은 컨테이너 쿼리의 잠재적인 타겟이 됩니다. 쿼리 안에 작성된 스타일은 너비가 10em 이상 20em 이하인 모든 폼의 자손들에게 적용됩니다.
<container-condition>에는 대소문자를 구분하는 container-name을 선택적으로 포함할 수 있습니다. 컨테이너 이름을 지정하면 조건이 훨씬 더 구체적이 됩니다. 쿼리가 오직 해당 이름을 container-name 속성으로 가지고 있는 요소들에 대해서만 평가되기 때문이죠.
container-name 속성은 @container 규칙에서 사용할 수 있는 쿼리 <container-name> 값들의 목록을 지정합니다. 이 이름들은 대소문자를 구분하는 <ident> 값이어야 합니다. 이름을 명시하면 요소의 조상 중 특정한 컨테이너를 골라서 타겟팅할 수 있습니다. 반면 컨테이너 이름이 없으면 쿼리는 항상 조건을 만족하는 '가장 가까운' 조상 컨테이너만 타겟팅합니다.
@container [ [ <container-name> ]? <container-query> ]# {
/* <stylesheet> */
}
@container 규칙에 이름을 추가한 후에는, container-name 속성이나 container 단축 속성을 사용해서 특정 컨테이너 요소를 타겟팅할 수 있습니다. 이름이 지정된 @container 안에 있는 스타일들은, 해당 이름이 부여되어 있으면서 컨테이너 쿼리의 조건을 만족하는 컨테이너 내부의 요소들에게만 적용됩니다.
@container card (orientation: landscape) {
/* styles */
}
.todo-panel > li {
container-type: inline-size;
container-name: card;
}
위의 예제에서 컨테이너 쿼리 블록 내의 스타일은 너비가 높이보다 큰(landscape) 모든 <li> 요소의 자손들에게 적용될 것입니다. 참고로, container-name: card가 적용되어 있고 크기 조건까지 만족하는 다른 어떤 요소가 있다면, 그 요소의 자손들에게도 이 스타일이 똑같이 적용됩니다.
@container wide (width >= 20em) {
/* 넓은 .sizeContainer의 자손에게 적용될 스타일 */
}
@container narrow (width < 20em) {
/* 좁은 .sizeContainer의 자손에게 적용될 스타일 */
}
.sizeContainer {
container-type: size;
container-name: wide narrow;
}
위 예제에서 요소는 wide와 narrow라는 두 개의 컨테이너 이름을 가지고 있습니다. class="sizeContainer"를 가진 요소의 자손들은 조건에 따라 wide 또는 narrow 쿼리의 스타일을 적용받게 됩니다.
기본값인 container-type: normal은 해당 요소가 '크기' 컨테이너가 되는 것을 막지만, 여전히 '스타일' 컨테이너로는 동작할 수 있습니다. 기본값인 container-name: none은 컨테이너에 이름이 없음을 의미하지만, 요소가 이름이 지정되지 않은(unnamed) 쿼리에 매칭되는 것까지 막지는 않습니다.
컨테이너 쿼리는 크기만 쿼리할 수 있는 게 아닙니다! 컨테이너의 '스타일 특징'도 쿼리할 수 있습니다.
컨테이너 스타일 쿼리는 하나 이상의 style() 함수 표기법에 정의된 대로 컨테이너 요소의 계산된 스타일(computed styles)을 평가하는 @container 쿼리입니다. 스타일 특징들을 하나의 스타일 쿼리로 결합하는 논리 연산자(and, or, not) 문법은 CSS 기능 쿼리(CSS feature queries)에서 사용하는 것과 완전히 똑같습니다. 유일한 차이점은 함수 이름뿐입니다. 기능 쿼리에서는 <support-condition> 안에 supports()를 쓴다면, 스타일 쿼리에서는 <style-feature> 안에 style()을 씁니다.
@container style(<style-feature>),
not style(<style-feature>),
style(<style-feature>) and style(<style-feature>),
style(<style-feature>) or style(<style-feature>) {
/* <stylesheet> */
}
각 style() 함수의 매개변수는 단일 <style-feature>입니다. CSS 격리 명세서(containment specification)에 따르면, <style-feature>는 유효한 CSS 선언(declaration), CSS 속성, 또는 <custom-property-name>이 될 수 있습니다. 하지만 현재 브라우저에서 지원되는 스타일 특징은 오직 커스텀 속성(CSS 변수)뿐입니다 (값 포함 여부와 무관). 자세한 내용은 @container의 브라우저 호환성 표를 참고하세요.
<style-feature>가 값을 포함하는 경우, style() 인수로 전달된 커스텀 속성(또는 미래에는 CSS 선언)의 계산된 값이 쿼리 대상 컨테이너의 값과 정확히 일치할 때 참(true)으로 평가됩니다. 일치하지 않으면 거짓(false)이 됩니다.
값이 없는 스타일 특징(이름만 있는 경우)은 해당 속성의 계산된 값이 초깃값(initial value)과 '다를 때' 참으로 평가됩니다.
미래에는 다음과 같이 다양한 스타일 쿼리를 작성할 수 있게 될 것입니다:
@container style(color: green) and style(background-color: transparent),
not style(background-color: red),
style(--themeBackground),
style(--themeColor: blue) or style(--themeColor: purple),
(width <= 100vw) and style(max-width: 600px) {
/* <stylesheet> */
}
style() 함수 표기법은 스타일 쿼리와 크기 쿼리를 구별하기 위해 사용됩니다. 아직 지원되지는 않지만, 머지않아 max-width: 600px 같은 일반적인 CSS 선언도 쿼리할 수 있게 될 것입니다.
@container (max-width: 600px)를 쿼리하는 것은 크기 쿼리입니다. 이를 위해서는 container-type이나 container 단축 속성을 통한 격리 설정이 필요하며, 컨테이너의 크기가 600px 이하일 때 참을 반환합니다.
반면 @container style(max-width: 600px)를 쿼리하는 것은 스타일 쿼리입니다. 이것이 지원되면, 컨테이너의 max-width 속성값이 딱 600px로 설정되어 있을 때만 참을 반환할 것입니다.
일반 CSS 선언과 속성에 대한 스타일 쿼리가 공식적으로 지원될 때까지, 우리는 style() 매개변수로 커스텀 속성(값 포함/미포함)만을 사용해야 하는 제한이 있습니다:
@container style(--themeBackground),
style(--themeColor: blue) or style(--themeColor: purple) {
/* <stylesheet> */
}
앞서 언급했지만 꼭 기억해야 할 몇 가지 중요 사항을 짚어보겠습니다:
container-type을 설정할 필요가 없습니다. 자손 요소의 스타일이 조상 요소의 계산된 스타일에 영향을 미치지 않기 때문에, 스타일 쿼리에서는 격리(containment) 설정이 필요 없습니다.<container-condition>은 스타일 특징과 크기 특징을 동시에 포함할 수 있습니다. 단, 쿼리에 크기 특징을 포함하려면 컨테이너 요소에 반드시 container-type을 size 또는 inline-size로 설정해 두어야 합니다.container-name을 부여해버리세요. container-name: none으로 설정하는 것은 컨테이너에 연결된 쿼리 이름을 지우는 것일 뿐, 해당 요소가 이름 없는 스타일 컨테이너로 동작하는 것까지 막지는 못합니다.style() 쿼리 내에서 CSS 커스텀 속성(변수) 값에 대해서만 작동합니다.💡 강사의 실무 팁!
"스타일 쿼리는 격리(container-type)를 선언하지 않아도 된다"는 점이 매우 중요합니다. 크기를 계산하는 것과 달리 부모의 배경색이나 변수값을 읽어오는 것은 렌더링 성능에 큰 부담을 주지 않기 때문이죠.
이제 다양한 <style-feature> 유형에 대해 자세히 알아보겠습니다.
커스텀 속성을 위한 스타일 쿼리를 사용하면 부모 요소의 커스텀 속성(일명 "CSS 변수")을 쿼리할 수 있습니다. 기능 쿼리에서 일반 CSS 속성을 다루는 것과 똑같은 방식으로 <style-query> 안에 포함시킬 수 있으며, 값을 명시할 수도 있고 생략할 수도 있습니다.
style() 함수 표기법의 <style-query> 매개변수에는 값 없이 CSS 변수 이름만 딱 들어갈 수 있습니다. 값을 포함하지 않은 경우, 해당 변수의 값이 @property @규칙 내에 설정된 initial-value 값과 같다면 쿼리는 거짓(false)을 반환합니다. 반대로 커스텀 속성값이 initial-value와 다를 때, 혹은 @property로 등록되지 않은 변수가 어떤 값이라도 가지고 있을 때는 참(true)을 반환하여 요소들과 매칭됩니다.
일반적인 변수 선언(값 할당)을 통해 CSS 변수가 도입된 경우, 값이 없는 커스텀 속성 쿼리는 항상 참(true)을 반환합니다.
:root {
--theme-color: rebeccapurple;
}
@container style(--theme-color) {
/* <stylesheet> */
}
이 예제에서 컨테이너 쿼리는 --theme-color 속성이 선언된 요소와 그 요소의 모든 자손들과 매칭됩니다. CSS 변수 --theme-color가 :root에 선언되었기 때문에, 스타일 쿼리 style(--theme-color)는 해당 DOM 트리의 모든 요소에 대해 참이 됩니다.
하지만 등록된 커스텀 속성의 동작은 좀 다릅니다. @property CSS @규칙이나 자바스크립트의 CSS.registerProperty() 메서드를 통해 명시적으로 정의된 경우, style(--theme-color) 쿼리는 요소의 --theme-color 계산된 값이 커스텀 속성 원본 정의에 설정된 initial-value와 다를 때만 참을 반환합니다.
@property --theme-color {
initial-value: rebeccapurple;
inherits: true;
}
:root {
--theme-color: rebeccapurple;
}
main {
--theme-color: blue;
}
@container style(--theme-color) {
/* <stylesheet> */
}
이 예제에서 :root 요소는 스타일 쿼리와 매칭되지 않습니다. 왜냐하면 커스텀 속성의 현재 값(rebeccapurple)이 initial-value 값과 완전히 같기 때문입니다. :root 요소(그리고 그 값을 상속받는 모든 요소)의 커스텀 속성값은 여전히 rebeccapurple입니다. 오직 초깃값과 달라진 요소들, 즉 이 경우에는 --theme-color: blue로 덮어씌워진 <main> 요소와 그 변경된 값을 상속받는 <main>의 자손들만이 쿼리와 매칭됩니다.
스타일 쿼리에 커스텀 속성의 '값'까지 포함되어 있다면, 요소의 해당 속성에 대한 계산된 값은 쿼리에 명시된 값과 정확히 일치해야 합니다. 만약 커스텀 속성이 syntax 설명자를 포함하여 @property @규칙(또는 CSS.registerProperty() 메서드 호출)으로 정의되어 있다면, 의미상 완전히 똑같은(equivalent) 값들도 일치하는 것으로 인정됩니다.
@container style(--accent-color: blue) {
/* <stylesheet> */
}
이 컨테이너 스타일 쿼리는 --accent-color 커스텀 속성의 계산된 값(computed value)이 딱 blue인 모든 요소와 매칭됩니다.
여기서 blue와 시각적으로 동일한 sRGB 값들(예: 헥스 코드 #0000ff)이 매칭되려면, 사전에 --accent-color 속성이 @property나 CSS.registerProperty()를 통해 명확한 '색상(color)' 타입으로 정의되어 있어야 합니다:
@property --accent-color {
syntax: "<color>";
inherits: true;
initial-value: #0000ff;
}
이렇게 명시적으로 정의해 두면, --accent-color의 값이 blue, #00f, #0000ff, rgb(0 0 255 / 1), 또는 rgb(0% 0% 100%) 중 어떤 것으로 설정되어 있더라도 @container style(--accent-color: blue) 쿼리에 대해 참(true)을 반환하게 됩니다. 브라우저가 "아, 얘네들은 포맷만 다르고 다 똑같은 파란색이구나!" 하고 알아듣는 거죠.
이 예제에는 네 개의 라디오 버튼이 있는 <fieldset>이 있습니다. 네 번째 옵션에는 사용자가 직접 커스텀 색상을 입력할 수 있는 텍스트 <input>이 포함되어 있습니다.
<form>
<fieldset>
<legend>Change the value of <code>--theme</code></legend>
<ol>
<li>
<input type="radio" name="selection" value="red" id="red" />
<label for="red">--theme: red;</label>
</li>
<li>
<input type="radio" name="selection" value="green" id="green" />
<label for="green">--theme: green</label>
</li>
<li>
<input type="radio" name="selection" value="blue" id="blue" />
<label for="blue">--theme: blue</label>
</li>
<li>
<input type="radio" name="selection" value="currentColor" id="other" />
<label for="other">Other</label>
<label for="color">color:</label>
<input
text="checkbox"
name="selection-value"
value="currentColor"
id="color" />
</li>
</ol>
</fieldset>
<output>I change colors</output>
</form>
자바스크립트는 라디오 버튼이 선택될 때마다 <fieldset>과 <output> 요소의 조상인 <body> 요소의 CSS --theme 변수값을 업데이트합니다. 텍스트 <input>이 변경될 때는, other 라디오 버튼이 체크되어 있을 때만 other 라디오 버튼의 value가 업데이트되고, 결과적으로 --theme의 값도 함께 업데이트됩니다.
const radios = document.querySelectorAll('input[name="selection"]');
const body = document.querySelector("body");
const other = document.getElementById("other");
const color = document.getElementById("color");
for (const radio of radios) {
radio.addEventListener("change", (e) => {
body.style.setProperty("--theme", e.target.value);
});
}
color.addEventListener("input", (e) => {
other.style.setProperty("value", e.target.value);
if (other.checked) {
body.style.setProperty("--theme", e.target.value);
}
});
우리는 @property @규칙을 사용하여 --theme CSS 변수를 <color> 값 타입으로 정의하고, initial-value를 red로 설정합니다. 이렇게 하면 어떤 문법(예: red, rgb(255 0 0), #ff0000, #f00 모두 동등하게 취급됨)이 사용되든 동일한 색상은 확실하게 매칭되도록 보장할 수 있습니다.
@property --theme {
syntax: "<color>";
inherits: true;
initial-value: red;
}
output {
padding: 3px 5px;
margin-top: 5px;
}
첫 번째 스타일 기능 쿼리는 값이 없는 커스텀 속성입니다. 이 쿼리 타입은 커스텀 속성의 계산된 값이 해당 속성에 대해 지정된 initial-value와 다를 때 참(true)을 반환합니다. 이 경우에는 --theme의 값이 red와 의미상 동일한 값(예: #ff0000)이 아닌 다른 어떤 값일 때 참이 됩니다. 참이 되면, <output>은 5px의 점선 테두리(outline)를 갖게 됩니다. 테두리의 색상은 --theme의 현재 값이 적용됩니다. 기본 텍스트 color는 회색입니다.
@container style(--theme) {
output {
outline: 5px dotted var(--theme);
color: #777777;
}
}
두 번째와 세 번째 스타일 쿼리는 커스텀 속성의 값을 포함하고 있습니다. 이들은 컨테이너의 --theme 값이 나열된 값과 의미상 같은 색상일 때 매칭되며, 심지어 그 값이 initial-value와 같아도 무방합니다. 첫 번째(아래 코드 기준 위쪽) 쿼리는 --theme 값이 red, blue 또는 green과 같은 색상인 요소와 매칭됩니다. 매칭될 경우, color 속성은 --theme의 현재 색상값으로 바뀝니다 (따라서 blue와 green의 경우, 앞선 쿼리에서 설정된 회색 글씨를 덮어쓰게 됩니다).
아래쪽의 스타일 쿼리는 --theme이 red와 동일할 때 <output>의 내용물을 굵게(bold) 만듭니다. 우리는 컨테이너 쿼리가 매칭되고 있음을 시각적으로 더 잘 보여주기 위해 이 효과를 추가했습니다.
@container style(--theme: green) or style(--theme: blue) or style(--theme: red) {
output {
color: var(--theme);
}
}
@container style(--theme: red) {
output {
font-weight: bold;
}
}
(결과 화면에서 텍스트 박스에 여러 가지 색상 값을 입력해 보세요.) red와 동일한 sRGB 값을 입력하면 <output>이 빨간색으로 변하고 글씨가 굵어지는 반면 테두리(outline)는 사라지는 것을 알 수 있습니다. 왜냐하면 요소의 --theme 값이 @property 규칙으로 정의된 초깃값(red)과 똑같기 때문에 값 없는 style(--theme) 쿼리는 거짓(false)을 반환하기 때문입니다. 반면 currentColor나 hsl(180 100% 50%)을 포함하여 빨간색이 아닌 유효한 sRGB 색상을 입력하면 첫 번째 스타일 쿼리(style(--theme))가 참이 됩니다. 이 값들은 initial-value와 확실히 다르니까요.
우리가 syntax: "<color>";를 설정했기 때문에 이 CSS 변수에는 유효한 <color> 값만 할당할 수 있습니다. unset이나 inherit처럼 color 속성에 쓸 수는 있지만 <color> 데이터 타입 자체가 아닌 값들은 이 커스텀 속성에게는 유효하지 않은 값(invalid)으로 취급되어 무시됩니다.
만약 여러분이 unset이나 아무 말(예: gibberish)을 입력한다면, 자바스크립트는 <body>의 인라인 style을 --theme: unset 또는 --theme: gibberish로 업데이트할 것입니다. 둘 다 색상이 아닙니다. 둘 다 유효하지 않으므로 철저히 무시됩니다. 이는 곧 initial-value(red)가 그대로 상속되어 변하지 않음을 의미하며, 결과적으로 style(--theme) 쿼리는 거짓을, style(--theme: red) 쿼리는 참을 반환하게 만듭니다.
💡 노트 (Note):
커스텀 속성을 선언할 때는syntax설명자가 포함된@property를 사용하는 것을 적극 권장합니다. 그래야 브라우저가 계산된 값들을 똑똑하고 올바르게 비교할 수 있습니다.
컨테이너 쿼리는 다른 컨테이너 쿼리 내부에 중첩(nesting)될 수 있습니다. 겹겹이 중첩된 컨테이너 쿼리 안쪽에 정의된 스타일은, 요소 바깥을 감싸고 있는 모든 컨테이너 쿼리의 조건이 전부 참(true)일 때만 비로소 적용됩니다.
@container style(--theme: red) {
output {
outline: 1px dotted;
}
@container style(--theme: purple) {
output {
outline: 5px dotted;
}
}
}
이 경우, <output> 요소는 --theme: purple이 설정된 컨테이너 안에 있으면서, 동시에 그 purple 컨테이너가 다시 --theme 값이 red인 부모 컨테이너 안에 중첩되어 있을 때만 5px 점선 테두리를 갖게 됩니다.
아직 어떤 브라우저에서도 지원하지는 않지만, 미래에는 style() 함수 표기법 안에 CSS 속성과 값의 쌍을 포함하는 일반적인 CSS 선언(declarations)도 넣을 수 있게 될 것입니다.
@container style(font-weight: bold) {
b,
strong {
background: yellow;
}
}
지원되기 시작하면, 이 기초적인 예제는 부모 요소가 이미 bold 상태일 때 그 안의 모든 <b> 및 <strong> 요소의 배경색을 노란색으로 바꿀 것입니다.
매칭 작업은 부모 컨테이너의 '계산된 값(computed value)'을 기준으로 수행됩니다. 부모의 계산된 font-weight가 딱 bold라면 ( bolder나 900이 아닌 경우), 조건이 일치합니다. 커스텀 속성을 이용한 스타일 쿼리와 마찬가지로, 기본적으로 모든 요소가 스타일 컨테이너이므로 우리는 어떤 요소도 굳이 '스타일 컨테이너'라고 지정할 필요가 없습니다. 요소에 유효하지 않은 container-name이 설정되어 방해하지만 않는다면, 부모가 font-weight: bold를 직접 선언했거나 상속받아서 가지고 있으면 무조건 쿼리와 매칭됩니다.
단축 속성(shorthand property)을 조회하는 스타일 특징은, 그 단축 속성을 구성하는 각각의 모든 개별 속성(longhand properties)의 계산된 값들이 쿼리한 값과 완벽히 일치할 때만 참(true)을 반환하고, 그렇지 않으면 거짓(false)을 반환합니다. 예를 들어 @container style(border: 2px solid red)는 이 단축 속성을 구성하는 12개의 개별 속성(예: border-bottom-style 등)이 전부 동일한 의미의 값으로 세팅되어 있을 때만 참으로 판별됩니다.
CSS의 전역 값인 revert와 revert-layer는 <style-feature> 안에 들어갈 값으로는 부적합(invalid)하며, 컨테이너 스타일 쿼리를 무조건 거짓(false)으로 만듭니다.
⚠️ 매우 중요한 주의사항!
스타일 쿼리에서 '조건으로 물어보는(querying)' 바로 그 스타일 속성을, 해당 쿼리가 적용되는 자식 요소에 다시 스타일링 용도로 적용하지 마세요. 무한 루프(infinite loop)를 일으킬 위험이 있습니다!
또한 스타일 쿼리는 속성 이름만 덩그러니 놓는 불리언(boolean) 컨텍스트의 속성 조회도 허용할 것으로 예상됩니다. 이 스타일 쿼리는 해당 속성의 값이 (아무도 건드리지 않아서) 초깃값 그대로라면 거짓을 반환하고, 뭔가 다른 값으로 바뀌었다면 참을 반환하게 될 것입니다.
@container style(font-weight) {
}
위의 예제는 font-weight의 값이 초깃값과 '다른' 모든 요소에 대해 참을 반환할 것입니다. 예를 들어, 브라우저가 기본으로 제공하는 유저 에이전트(User-agent) 스타일시트는 제목 태그(heading elements)와 <th> 요소에 font-weight: bold를 설정합니다. 어떤 브라우저는 <strong>과 <b>를 bold로, 다른 브라우저는 bolder로 설정하기도 하죠. <optgroup> 요소 역시 종종 유저 에이전트에 의해 normal이 아닌 다른 font-weight가 설정되곤 합니다. 이렇게 요소의 font-weight가 기본값이 아니라면, 해당 스타일 쿼리는 참을 반환할 것입니다.
(다시 말씀드리지만, 일반 속성에 대한 스타일 쿼리는 아직 어떤 브라우저에서도 지원되지 않습니다.)
@container @규칙contain 속성container 단축 속성container-name 속성aspect-ratio 이해하기 (Understanding aspect-ratio)이 페이지가 도움이 되셨나요?
기여하는 방법 알아보기 (Learn how to contribute)
이 페이지는 MDN 기여자들에 의해 2026년 3월 20일에 마지막으로 수정되었습니다 (MDN contributors).