Contents
see List화면 크기만으로는 해결되지 않는 반응형 문제
일반적인 반응형 CSS는 뷰포트 너비를 기준으로 미디어 쿼리를 작성한다. 페이지 전체가 넓으면 3열, 좁으면 1열처럼 화면 단위의 변화에는 효과적이다. 그러나 같은 카드 컴포넌트가 메인 영역에서는 넓게, 사이드바에서는 좁게, 모달 안에서는 다시 다른 폭으로 놓이는 경우에는 뷰포트 기준만으로 적절한 레이아웃을 만들기 어렵다. 컴포넌트 내부에서 필요한 정보는 브라우저 창의 크기가 아니라 자신에게 실제로 배정된 컨테이너의 폭이기 때문이다.
CSS Container Query는 이 문제를 해결한다. 부모 요소를 컨테이너로 선언하고, 자식 컴포넌트가 그 컨테이너의 인라인 크기에 따라 스타일을 바꾸게 한다. 하나의 컴포넌트를 여러 화면과 레이아웃에 재사용할 때 조건문이나 별도 변형 클래스를 과도하게 추가하지 않아도 된다. 특히 관리자 화면, 대시보드, 상품 목록, 뉴스 카드처럼 영역이 자주 재배치되는 서비스에서 유지보수 비용을 줄이는 데 유용하다.
먼저 컨테이너 경계를 명확하게 선언하기
컨테이너 쿼리는 아무 부모에서나 자동으로 동작하지 않는다. 크기를 관찰할 요소에 container-type: inline-size를 지정해야 한다. inline-size는 글쓰기 방향의 가로 길이를 의미하며, 일반적인 한국어 웹 페이지에서는 폭으로 생각하면 된다. 이름을 지정하면 중첩된 레이아웃에서도 어느 컨테이너를 기준으로 할지 명확해진다.
<section class="dashboard-panel">
<article class="product-card">
<img src="/images/product.webp" alt="무선 키보드">
<div class="product-card__body">
<p class="product-card__category">주변기기</p>
<h3>업무용 무선 키보드</h3>
<p class="product-card__description">사무 환경에 맞는 연결과 배터리 정보를 제공합니다.</p>
</div>
</article>
</section>
.dashboard-panel {
container-type: inline-size;
container-name: dashboard;
}
.product-card {
display: grid;
gap: 16px;
padding: 16px;
border: 1px solid #d8dde5;
border-radius: 12px;
}
.product-card img {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
border-radius: 8px;
}컨테이너 선언은 페이지의 최상위 요소에 습관적으로 넣기보다, 컴포넌트가 실제로 배치되는 슬롯에 둔다. 예시에서는 .dashboard-panel이 카드의 사용 가능한 폭을 결정한다. 카드 자신에게 컨테이너를 지정하면 자기 크기를 자기 스타일의 조건으로 직접 참조할 수 없으므로, 한 단계 바깥 래퍼에 선언하는 방식이 안전하다.
카드 내부 레이아웃을 컨테이너 폭으로 전환하기
이제 @container 규칙 안에 넓은 영역에서만 필요한 가로 배치와 설명 노출을 작성한다. 640px이라는 수치는 시작점일 뿐이다. 실제 카드에서 제목이 두 줄을 넘기기 시작하는 지점, 이미지와 텍스트가 답답해지는 지점을 브라우저 개발자 도구에서 확인해 조정해야 한다. 뷰포트가 1440px이어도 사이드바 안의 카드 폭이 320px이면 기본 세로 레이아웃이 유지된다.
@container dashboard (min-width: 640px) {
.product-card {
grid-template-columns: minmax(180px, 0.9fr) minmax(0, 1.1fr);
align-items: center;
}
.product-card img {
aspect-ratio: 4 / 3;
}
.product-card__description {
display: block;
}
}
@container dashboard (max-width: 399px) {
.product-card {
padding: 12px;
gap: 10px;
}
.product-card__description {
display: none;
}
}minmax(0, 1.1fr)는 긴 제목이나 URL이 그리드 열의 최소 너비를 밀어내는 문제를 줄인다. 텍스트가 외부 데이터에서 들어오는 서비스라면 제목에도 overflow-wrap: anywhere를 적용하고, 이미지를 숨기기보다 대체 텍스트와 핵심 정보를 먼저 보존하는 것이 좋다. 설명을 작은 폭에서 감출 때도 제목, 상태, 가격처럼 업무 판단에 필요한 정보까지 함께 숨기지 않는지 확인한다.
미디어 쿼리와의 역할을 나누기
Container Query가 미디어 쿼리를 완전히 대체하지는 않는다. 전역 내비게이션의 접기, 페이지 여백, 모바일 전용 상호작용처럼 기기 화면 자체에 관한 판단은 여전히 @media가 적합하다. 반면 카드, 테이블 행, 필터 패널, 프로필 요약처럼 다른 위치로 옮겨 재사용될 수 있는 요소는 컨테이너 쿼리를 우선 검토한다. 이 기준을 정해 두면 동일한 스타일 변경이 여러 뷰포트 규칙에 흩어지는 일을 피할 수 있다.
- 페이지 전체의 구조 변화는 미디어 쿼리로 관리한다.
- 독립 컴포넌트의 밀도와 배치는 컨테이너 쿼리로 관리한다.
- 중첩 컨테이너에는 이름을 붙여 기준 대상을 분명히 한다.
- 고정 폭보다
minmax(),clamp(), 유동 단위를 함께 사용한다.
도입 전 테스트 체크리스트
첫 적용 대상은 이미 여러 영역에서 재사용되는 카드나 검색 필터가 적합하다. 데스크톱·태블릿·모바일 뷰포트만 확인하지 말고, 넓은 본문, 좁은 사이드바, 모달, 분할 화면처럼 같은 컴포넌트의 실제 배치 폭을 각각 시험한다. 긴 한국어 제목, 빈 이미지, 확대된 브라우저 글꼴, 키보드 탐색에서도 정보와 포커스가 유지되는지 확인해야 한다. 컨테이너의 기준을 명확히 하고 전역 반응형과 컴포넌트 반응형을 분리하면, 화면 조합이 늘어나도 CSS를 예측 가능하게 운영할 수 있다.
html
| No | 작성일 | Title |
|---|---|---|
| 3300 | 2026. 07. 30. | CSS Container Query 실전 적용: 컴포넌트가 놓인 영역에 맞춰 반응형 만들기 |
| 3269 | 2026. 07. 22. | 접근성 있는 모달 만들기: HTML dialog와 포커스 관리 실전 가이드 |
| 3241 | 2026. 07. 14. | 반응형 이미지 최적화: picture·srcset·sizes로 모바일 전송량 줄이기 |
| 3186 | 2026. 07. 05. | HTML Popover API로 자바스크립트 드롭다운 메뉴 줄이기 |
| 3144 | 2026. 06. 27. | CSS 컨테이너 쿼리 운영 가이드: 화면이 아니라 컴포넌트 폭에 맞춰 레이아웃 바꾸기 |
| 3088 | 2026. 06. 19. | 접근성 있는 모달 창 구현: dialog, focus, 닫기 동작을 함께 설계하기 |
| 2999 | 2026. 06. 11. | HTML 폼 검증 운영 가이드: 브라우저 기본 검증과 서버 검증을 함께 설계하기 |
| 2943 | 2026. 06. 03. | CSS 컨테이너 쿼리 실전 적용: 화면이 아니라 컴포넌트 너비에 맞춰 카드 레이아웃 바꾸기 |
| 2888 | 2026. 05. 26. | 반응형 이미지 운영 가이드: srcset, sizes, picture, lazy loading으로 LCP와 트래픽 줄이기 |
| 2824 | 2026. 05. 18. | 실무 문의 폼 접근성 점검: fieldset, autocomplete, Constraint Validation API 적용법 |