웹사이트를 만들다 보면 같은 카드 컴포넌트를 여러 곳에 재사용한다. 넓은 본문 영역에서는 사진과 글이 가로로 나란히 잘 놓이는데, 똑같은 카드를 좁은 사이드바에 넣는 순간 글자가 줄바꿈되고 버튼이 삐져나온다. 분명 반응형으로 만들었는데 왜 이런 일이 생길까.
미디어 쿼리는 '화면'을 보고, 컨테이너 쿼리는 '자리'를 본다
지금까지의 반응형은 전부 화면 전체 너비를 기준으로 했다. @media (min-width: 768px)는 "브라우저 창이 768px보다 넓으면"이라는 뜻이다. 그래서 화면은 넓어도 카드가 놓인 사이드바는 좁은 상황을 구분하지 못한다. 예전에는 이걸 해결하려고 자바스크립트로 요소 너비를 계속 측정(ResizeObserver)하고 클래스를 갈아 끼웠다. 컨테이너 쿼리(@container)는 이 일을 CSS만으로 끝낸다. 요소가 자기를 감싼 부모의 너비를 보고 스스로 모양을 바꾼다.
원칙 1. 기준이 될 부모를 먼저 '컨테이너'로 선언한다
컨테이너 쿼리는 아무 요소나 기준으로 삼지 못한다. 먼저 기준이 될 부모에 container-type: inline-size를 지정해 "이 박스의 가로 크기를 기준으로 삼겠다"고 알려줘야 한다. 이름까지 붙여두면(container-name) 어느 컨테이너를 볼지 명확해져, 컨테이너가 중첩됐을 때도 헷갈리지 않는다.
원칙 2. '화면'이 아니라 '자리' 기준으로 분기한다
선언이 끝나면 @container (min-width: 400px)처럼 쓴다. 이제 카드는 화면이 아니라 자기가 놓인 칸이 400px보다 넓을 때만 가로 배치로 바뀐다. 같은 카드를 본문에 넣으면 가로로, 사이드바에 넣으면 세로로 — 마크업을 따로 분기하지 않고 알아서 적응한다.
원칙 3. 컨테이너 기준 단위(cqw)로 글자까지 맞춘다
레이아웃뿐 아니라 글자 크기도 자리에 맞출 수 있다. cqw(컨테이너 너비의 1%) 같은 단위를 쓰면 좁은 칸에서는 제목이 작아지고 넓은 칸에서는 커진다. 뷰포트 단위(vw)가 화면 전체를 따라가던 것과 달리, 이 단위는 컴포넌트 안에서만 비례하므로 어느 자리에 놓아도 균형이 깨지지 않는다.
원칙 4. 지원 범위를 확인하고 안전하게 적용한다
컨테이너 쿼리는 2023년부터 크롬·사파리·파이어폭스 최신 버전에서 모두 지원된다. 다만 오래된 브라우저를 쓰는 고객이 있다면, 기본 스타일을 세로 배치로 깔아두고 컨테이너 쿼리로 가로 배치를 '추가'하는 방식이 안전하다. 지원이 안 되는 환경에서도 최소한 읽을 수 있는 형태가 유지되기 때문이다.
원칙 5. 재사용하는 컴포넌트부터 적용한다
모든 곳에 한꺼번에 도입할 필요는 없다. 여러 위치에서 똑같이 쓰이는 조각부터 시작하는 게 효율이 가장 높다. 대표적으로 이런 것들이다.
- 상품·서비스 카드 — 목록 3열, 본문 1열, 사이드바 추천 등 폭이 제각각인 자리에 동시에 쓰인다.
- 후기·인용 박스 — 넓은 곳에선 사진과 글을 나란히, 좁은 곳에선 위아래로 쌓는다.
- 가격표·CTA 블록 — 같은 박스를 랜딩과 사이드바에 함께 배치하는 경우가 많다.
결국 컨테이너 쿼리는 "화면이 아니라 자리에 맞춘다"는 한 문장으로 요약된다. 작은 회사 웹사이트일수록 페이지 수는 적어도 같은 컴포넌트를 이리저리 재사용하기 마련이라, 이 기능 하나로 유지보수가 눈에 띄게 가벼워진다. CYAN은 작은 회사의 웹사이트를 만들 때 처음부터 컴포넌트를 컨테이너 기준으로 설계해, 새 페이지에 같은 조각을 가져다 놓아도 손볼 곳 없이 자연스럽게 자리 잡도록 한다.