--- id: frontend-container-queries title: Container Queries — Component-level Responsive category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [frontend, css, responsive, vibe-coding] tech_stack: { language: "CSS", applicable_to: ["Frontend"] } applied_in: [] aliases: [container query, @container, container-type, cqw, cqi, intrinsic sizing] --- # Container Queries > Media query = viewport. **Container query = parent element**. Component 가 자기 container size 따라 변형. 2023+ 모든 modern browser 지원. ## 📖 핵심 개념 - @container: 가장 가까운 named container 의 size. - container-type: size / inline-size / normal. - cqw / cqi / cqh / cqb: container 단위. - Style query (실험): variable 값 따라. ## 💻 코드 패턴 ### 기본 ```css .card-container { container-type: inline-size; container-name: card; } .card { display: flex; flex-direction: column; } @container card (min-width: 400px) { .card { flex-direction: row; } } ``` ```html
Content
``` → Container 가 400px 이상 = horizontal. 미만 = vertical. Viewport 무관. ### 사용 예 — 같은 component, 다른 layout ```html
``` → 같은 component 가 위치별 다른 layout. ### Container types ```css .container-1 { container-type: inline-size; /* width 만 (most common) */ } .container-2 { container-type: size; /* width + height */ } .container-3 { container-type: normal; /* default — query target X */ } ``` ### Container units ```css .text { font-size: 5cqi; /* 5% of container's inline size */ padding: 2cqw; /* width % */ margin: 1cqh; /* height % (size container 만) */ } ``` → Container 따라 자동 scale. ### Multiple containers ```css .grid { container-type: inline-size; container-name: grid; } .card { container-type: inline-size; container-name: card; } @container grid (min-width: 600px) { .card { background: blue; } } @container card (min-width: 300px) { .card { padding: 2rem; } } ``` ### Ranges ```css @container card (300px <= width <= 600px) { .card { background: yellow; } } @container card (width > 600px) { .card { background: green; } } ``` ### React component ```tsx function ProductCard({ product }: ...) { return (

{product.name}

{product.price}

); } ``` ```css .product-card { display: flex; flex-direction: column; gap: 8px; } .product-card img { width: 100%; } @container product (min-width: 400px) { .product-card { flex-direction: row; } .product-card img { width: 40%; } } @container product (min-width: 700px) { .product-card { padding: 2rem; gap: 2rem; } } ``` ### Tailwind 4 (built-in support) ```html
...
``` → `@container` 만 + Tailwind 가 처리. ### vs Media query ``` Media query: viewport @media (min-width: 768px) { // 모든 컴포넌트가 같은 breakpoint } Container query: parent @container (min-width: 400px) { // 이 component 의 parent 가 400px+ 면 } ``` → Component-driven. ### 사용 시나리오 ``` - Sidebar 안 card 가 다르게 보임 - Modal 안 vs page 안 같은 form 다르게 - Dashboard widget — 어디 둬도 OK - Email-style nested layout - 큰 화면에 multi-column page ``` ### Style queries (실험) ```css .parent { container-name: theme-container; --theme: dark; } @container theme-container style(--theme: dark) { .button { background: white; color: black; } } ``` → CSS variable 따라 styling. 매우 새. Limited support. ### Browser support ``` Chrome 105+ (2022) Safari 16.0+ (2022) Firefox 110+ (2023) → 2024+ 거의 안전. Polyfill: container-query-polyfill (legacy) ``` ### Performance ``` Container query = element 의 layout 변경. Layout invalidation 트리거. 큰 nested = 비싸 수 있음. → 매번 측정 — 보통 OK, 큰 페이지는 주의. ``` ### Anti-pattern: 모든 곳 container ```css /* ❌ */ * { container-type: inline-size; } /* layout cost — 의미 없음 */ ``` ```css /* ✅ — 명시적 */ .card-container { container-type: inline-size; } ``` ### Inheritance ```css /* Container 가 nested */ @container outer (min-width: 800px) { @container inner (min-width: 300px) { .item { ... } } } ``` → 두 조건 모두 OK. ### JS 통합 ```ts // 동적 변경 element.style.containerType = 'inline-size'; // MutationObserver / ResizeObserver 와 같이 안 필요 — CSS 자동. ``` → JS 보다 CSS 가 빠름. ### Modal / popover ```css .modal { container-type: inline-size; width: clamp(300px, 80vw, 800px); } .modal-content { display: flex; flex-direction: column; } @container (min-width: 600px) { .modal-content { flex-direction: row; } } ``` → Modal size 변경 시 자동 layout 변경. ### Card grid + container query ```css .card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; } .card-grid > * { container-type: inline-size; } @container (min-width: 350px) { .card { ... } /* 큰 column 안 card 만 */ } ``` → Grid 의 column width 따라 card 다름. ### Subgrid + container query (modern) ```css .layout { display: grid; grid-template-columns: 1fr 3fr; container-type: inline-size; } @container (max-width: 600px) { .layout { grid-template-columns: 1fr; } } ``` ## 🤔 의사결정 기준 | 상황 | 추천 | |---|---| | Component-driven UI | Container query | | Page-level layout | Media query | | Reusable card / widget | Container query | | Print | @media print | | Theme switch | Style query (실험) | | Old browser support | Polyfill 또는 media query fallback | ## ❌ 안티패턴 - **모든 element container**: layout cost. - **Container query + media query 혼용 같은 결과**: media 만으로 충분 자주. - **container-type: size + inline 만 필요**: inline-size 가 충분. - **Tailwind 3 가정**: `@container` 는 4+. - **Polyfill 무 modern**: 거의 모든 browser 지원. - **Nested container 깊음**: layout 비싸. ## 🤖 LLM 활용 힌트 - container-type: inline-size + @container 표준. - Component-level responsive. - cqw / cqi 단위 활용. - Tailwind 4 의 @container 친화. ## 🔗 관련 문서 - [[Frontend_Tailwind_Architecture]] - [[React_Component_Composition]] - [[Frontend_A11y_Testing]]