컨테이너 쿼리는 컴포넌트가 ‘화면’이 아니라 ‘자기가 놓인 부모의 너비’에 반응하게 합니다. 그래서 한 번 잘 만든 카드를 어디에 끼워 넣어도 알아서 알맞게 변합니다. Findable은 재사용 컴포넌트의 반응형을 미디어 쿼리 대신 @container로 설계해, 어떤 자리에 놓여도 깨지지 않게 만듭니다.
요약
- 미디어 쿼리는 ‘화면 너비’, 컨테이너 쿼리는 ‘부모 너비’에 반응한다 — 그래서 컴포넌트가 자리에 맞춰 변한다.
- 크기 기반 컨테이너 쿼리는 Chrome 105+·Firefox 110+·Safari 16+에서 지원, 전 세계 약 95% 이상 — 실무에 바로 써도 된다.
cqi는 컨테이너 너비의 1% 단위(뷰포트 기준 vw의 컨테이너 버전). 논리 단위cqi·cqb를 권장.- 구형 브라우저는
@container를 무시 → 기본 스타일을 먼저 쓰면 깨지지 않는다(점진적 향상).
예전에 제 카드 컴포넌트가 사이드바에서 처참하게 찌그러진 적이 있습니다. 화면(뷰포트)은 1440px로 넓었고, 그래서 미디어 쿼리는 ‘넓은 화면용 가로 배치’를 적용했죠. 그런데 그 카드가 실제로 들어간 칸은 280px짜리 사이드바였습니다. 가로로 펼쳐질 자리가 없는데도 가로로 펼쳐지려다 글자가 두 줄로 깨졌습니다. 그날 깨달았습니다 — 컴포넌트가 봐야 하는 건 화면이 아니라 자기가 놓인 칸이라는 걸.
그래서, 화면 말고 컨테이너만 줄여보세요
아래 위젯에는 카드 하나와 슬라이더가 있습니다. 슬라이더로 컨테이너(부모 칸)만 줄여보세요. 브라우저 창은 그대로인데, 카드가 가로에서 세로로 알아서 바뀝니다. 이게 미디어 쿼리로는 안 되는 일입니다.
화면이 아니라 '컨테이너'에 반응
슬라이더로 컨테이너만 줄여보세요 — 뷰포트와 무관하게 카드가 세로로 바뀝니다.
컨테이너 너비에 맞춰 가로/세로로 재배치됩니다.
미디어 쿼리는 왜 부족할까요?
미디어 쿼리(@media)는 오직 하나만 봅니다 — 브라우저 창(뷰포트) 너비. 사이트 전체 레이아웃을 바꿀 땐 완벽합니다. 문제는 ‘조각’입니다. 카드·배너·가격표 같은 컴포넌트는 페이지마다 다른 너비의 칸에 들어갑니다. 같은 카드가 어떤 페이지에선 본문 전체 폭을, 어떤 페이지에선 3분할 그리드의 한 칸을 차지하죠. 미디어 쿼리는 이 ‘칸의 너비’를 전혀 모릅니다. 그래서 컴포넌트마다 “이 페이지에선 이렇게, 저 페이지에선 저렇게”를 따로 깔게 되고, 그게 유지보수 지옥의 시작입니다.
컨테이너 쿼리는 어떻게 다른가요?
핵심은 두 줄입니다. 먼저 부모를 “이건 컨테이너야”라고 지정하고(container-type: inline-size), 그 안의 자식이 @container (max-width: 420px)처럼 부모의 너비를 묻습니다. 화면이 아니라 부모요. 그래서 카드는 자기가 640px 칸에 있으면 가로로, 280px 칸에 있으면 세로로 — 페이지가 어디든, 창이 얼마든 상관없이 — 스스로 판단합니다. 위 위젯의 프레임이 바로 container-type: inline-size로 지정돼 있고, 슬라이더는 그 프레임의 max-width만 건드립니다.
cqi 단위는 또 뭔가요?
컨테이너 쿼리가 ‘분기’라면, 컨테이너 단위는 ‘유연한 값’입니다. 뷰포트 기준의 vw(1vw = 화면 너비의 1%)는 익숙하실 겁니다. cqi는 그 컨테이너 버전입니다 — 1cqi = 컨테이너 인라인 크기(가로쓰기에선 너비)의 1%. 그래서 font-size: clamp(16px, 4cqi, 22px)처럼 쓰면, 글자가 화면이 아니라 카드가 놓인 칸 크기에 맞춰 부드럽게 커지고 줄어듭니다. 글쓰기 방향에 안전한 논리 단위 cqi(인라인)·cqb(블록)를 기본으로 쓰는 것을 권합니다.
지금 실무에 써도 안전한가요?
네, 크기 기반 컨테이너 쿼리는 안전합니다. Chrome 105+, Firefox 110+, Safari 16+에서 지원되고, 2023년 이래 주요 브라우저에 모두 들어와 전 세계 사용 브라우저의 약 95% 이상을 커버합니다. 폴리필도 필요 없습니다. 다만 한 가지 구분이 있습니다 — 크기 쿼리는 안정적이지만, 스타일 쿼리(@container style())는 아직 Chrome·Edge 111+ 위주이고 Firefox·Safari는 개발 중입니다. 그래서 저는 주력은 크기 쿼리로 두고, 스타일 쿼리는 보조 향상으로만 신중히 씁니다. (지원 수치는 시점에 따라 바뀌므로 적용 직전 최신 현황을 한 번 더 확인합니다.)
제가 컴포넌트에 @container를 깔기 전에 확인하는 ‘안전 카드’입니다 — 크기 쿼리는 이미 실무 영역입니다.
스타일 쿼리(@container style())는 아직 보조 향상으로만 — 주력은 위 크기 쿼리에 둡니다.
구형 브라우저에서 깨지지 않게 하려면?
비결은 ‘순서’입니다. 컨테이너 쿼리를 모르는 브라우저는 @container 블록을 그냥 무시합니다 — 에러가 아니라 ‘못 본 척’이죠. 그래서 기본 스타일(예: 가로 배치)을 먼저 작성하고, @container 안에 변형(예: 세로 배치)을 넣습니다. 그러면 신형은 분기까지 누리고, 구형은 기본 스타일로 멀쩡히 보입니다. 화면이 절대 깨지지 않는 점진적 향상(progressive enhancement) 방식입니다.
그래서 우리는 어떻게 만드나요?
Findable에서 재사용 컴포넌트(카드·배너·가격 박스·CTA)는 거의 다 @container 기준으로 설계합니다. 그러면 디자이너가 같은 컴포넌트를 본문에 넣든 사이드바에 넣든, 개발자가 ‘이 자리용 예외’를 추가로 깔 필요가 없습니다. 한 번 잘 만든 조각이 어디 놓여도 알맞게 변하니, 페이지가 늘어도 코드가 함께 늘지 않습니다. 결과적으로 더 적은 코드로 더 일관된 화면이 나옵니다.
| 항목 | 미디어 쿼리만 | 컨테이너 쿼리 |
|---|---|---|
| 반응 기준 | 화면(뷰포트) 너비만 | 놓인 부모 칸의 너비 |
| 재사용성 | 자리마다 예외 스타일 추가 | 한 번 만들면 어디든 알맞게 |
| 정확도 | 좁은 칸에 들어가도 찌그러짐 | 실제 폭에 맞춰 재배치 |
| 유지보수 | 페이지 늘면 코드도 늘어남 | 조각 하나만 관리 |
작은 차이 같지만, 사이트 전체의 ‘태도’입니다
컨테이너 쿼리를 쓰는 사람은 컴포넌트를 ‘재사용되는 부품’으로 봅니다. 한 번 만들 때 제대로 만들어, 어디 놓여도 버티게 하죠. 이 태도가 폼·타이포·접근성·속도에도 똑같이 적용됩니다. 당신의 사이트, 어떤 컴포넌트부터 단단하게 만들어 드릴까요?
컨테이너 쿼리와 미디어 쿼리는 무엇이 다른가요?
컨테이너 쿼리는 지금 실무에 써도 되나요?
cqi 같은 컨테이너 단위는 무엇인가요?
오래된 브라우저에서는 어떻게 되나요?
스타일 쿼리(style query)도 쓸 수 있나요?
다른 담당자와의 연결
컴포넌트가 단단하려면 한 사람만으로는 부족합니다. 같은 태도를 가진 옆자리 동료들의 노트입니다.
반응형을 맡은 사람
화면 전체 레이아웃을 접는 기술.
레이아웃을 맡은 사람
Grid·Flex 칸 나누기의 원칙.
모바일 UX를 맡은 사람
엄지로 닿는 화면의 디테일.
위 위젯은 이 페이지에서 실제로 동작하는 container-type: inline-size + @container 코드입니다(외부 라이브러리 0). 브라우저 지원 수치(크기 쿼리 Chrome 105+·Firefox 110+·Safari 16+, 약 95%+, 2023~)는 공개 호환성 자료 기준이며 시점에 따라 변동합니다 — 적용 전 최신 현황을 확인하세요. 날조된 사례·수치는 사용하지 않았습니다.