컨테이너 쿼리 — 뷰포트가 아니라 "부모 너비"에 반응하기
미디어 쿼리는 화면 크기만 봅니다. 컨테이너 쿼리는 컴포넌트가 놓인 자리의 크기에 반응해, 진짜 재사용 가능한 컴포넌트를 만듭니다.
3분 읽기
미디어 쿼리(@media)는 뷰포트 크기만 압니다. 하지만 같은 카드 컴포넌트가 넓은 본문에 있을 때와 좁은 사이드바에 있을 때 다르게 보여야 한다면? 뷰포트는 그대로인데 말이죠. 컨테이너 쿼리가 이 문제를 정확히 풉니다.
컴포넌트가 자기 컨테이너에 반응한다
두 단계입니다. (1) 부모를 “컨테이너”로 선언하고, (2) 자식이 그 컨테이너 너비에 반응합니다.
/* 1) 부모를 컨테이너로 */
.card-wrap {
container-type: inline-size;
container-name: card;
}
/* 2) 컨테이너가 400px 이상이면 가로 레이아웃 */
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 120px 1fr;
}
}
이제 .card는 어디에 놓이든 자기 부모 폭에 따라 알아서 배치를 바꿉니다. 사이드바(좁음)에선 세로, 본문(넓음)에선 가로 — 뷰포트와 무관하게요.
왜 이게 “진짜 재사용”인가
미디어 쿼리 기반 컴포넌트는 항상 “이 컴포넌트가 화면 전체 폭을 차지한다”는 암묵적 가정을 깔고 있습니다. 그래서 레이아웃이 바뀌면 매번 브레이크포인트를 손봐야 했죠. 컨테이너 쿼리는 그 결합을 끊습니다 — 컴포넌트는 자기 문맥만 알면 됩니다.
컨테이너 단위
컨테이너 크기에 비례하는 길이 단위도 함께 옵니다.
.card h3 {
font-size: clamp(1rem, 5cqi, 1.5rem); /* cqi = 컨테이너 인라인 크기의 1% */
}
cqw/cqh: 컨테이너 너비/높이의 1%cqi/cqb: 인라인/블록 축 기준 (쓰기 방향에 안전)
알아둘 점
- 지원: 모든 최신 브라우저에서 사용 가능합니다(2023년 Baseline).
- 주의: 컨테이너로 지정한 요소는 크기 계산 방식이 바뀌므로,
container-type: inline-size는 보통 “인라인(가로) 축”에만 적용해 높이 붕괴를 피합니다. - 스타일 쿼리(
@container style(...))는 컨테이너의 CSS 변수 값에 반응하는 더 최신 기능으로, 지원이 아직 고르지 않으니 타겟 확인 후 사용하세요.
디자인 시스템/컴포넌트 라이브러리를 만든다면 컨테이너 쿼리는 선택이 아니라 기본기입니다. “이 컴포넌트는 얼마나 넓은 자리에 놓일지 모른다”는 전제로 스타일을 짜세요.