WEB Log

개인 일상을 기록합니다.

목록으로

CSS @container — Optional Query Conditio

기존에는 @container 규칙을 쓸 때 조건(query)이 필수라고 인식하는 경우가 많았지만, 스펙 상 <container-name><container-query>하나 이상만 있으면 됩니다.

즉, 쿼리 조건 없이 컨테이너 이름만으로도 @container 블록을 선언할 수 있습니다.


문법 구조

@container [<container-name>]? [<container-query>]? { ... }
형태예시의미
조건만@container (width > 400px)가장 가까운 컨테이너의 크기 조건
이름 + 조건@container sidebar (width > 400px)sidebar 컨테이너의 크기 조건
이름만@container sidebarsidebar 컨테이너 안에 있을 때
조건 리스트@container (조건A), style(--x: y)여러 조건 중 하나라도 참이면

예시 코드

기본 — 이름만으로 스코핑

/* 컨테이너 선언 */
header { container: header / inline-size; }
.sidebar { container: sidebar / inline-size; }
main { container: main / inline-size; }
footer { container: footer / inline-size; }
/* 이름만으로 스코핑 — 크기 조건 없이 컨텍스트만으로 분기 */
@container sidebar {
.card { font-size: .875rem; flex-direction: column; }
}
@container main {
.card { font-size: 1rem; display: grid; }
}
@container footer {
.card { display: none; }
}

이름 + 크기 조건 조합

/* sidebar 안에서 + 너비 조건 추가 */
@container sidebar (width > 240px) {
.card { flex-direction: row; }
}
/* main 안에서 + 너비 조건 추가 */
@container main (width > 600px) {
.card { grid-template-columns: repeat(3, 1fr); }
}

조건 리스트 (OR 동작)

/* 쉼표로 구분 — 하나라도 true면 적용 */
@container card (width > 400px), style(--responsive: true), scroll-state(stuck: top) {
h2 { font-size: 1.5em; }
}

왜 유용한가?

컴포넌트 재사용 — “컨텍스트 네임스페이스”

같은 .card 컴포넌트 하나를 만들어두면, 어느 컨테이너 안에 놓이느냐에 따라 자동으로 다른 스타일이 적용됩니다.

/* before — 영역별로 클래스를 따로 만들어야 했음 */
.sidebar__card { ... }
.main__card { ... }
.footer__card { ... }
/* after — 컴포넌트 하나 + @container 이름 스코핑 */
.card { ... } /* 하나만 */
@container sidebar { .card { ... } }
@container main { .card { ... } }

크기를 몰라도 되는 경우

너비/높이 조건 없이 “이 레이아웃 영역 안에 있다”는 사실 자체만으로 스타일을 분기해야 할 때 유용합니다.

예: sidebar는 항상 compact, footer는 항상 숨김 등


브라우저 지원

/* 지원 여부 확인 후 적용 */
@supports (container-type: inline-size) {
header { container: header / inline-size; }
}

MDN 참고 예시

/* With a <size-query> */
@container (width > 400px) { h2 { font-size: 1.5em; } }
/* With an optional <container-name> */
@container tall (height > 30rem) { p { line-height: 1.6; } }
/* With a <container-name> only (query is optional) */
@container sidebar { h2 { background: blue; } }
/* With a <scroll-state> */
@container scroll-state(scrollable: top) {
.back-to-top-link { visibility: visible; }
}
/* Multiple queries in a single condition */
@container (width > 400px) and style(--responsive: true) {
h2 { font-size: 1.5em; }
}
/* Condition list */
@container card (width > 400px), style(--responsive: true), scroll-state(stuck: top) {
h2 { font-size: 1.5em; }
}

참고