css · high priority
모던 CSS 레이아웃 — Container Queries · :has() · Subgrid · Cascade Layers
*뷰포트 기반 반응형* 의 한계를 넘어 — 컴포넌트 단위 반응형, 부모 셀렉터, 자식 격자 정렬, 명시도 정복
학습 개요
탄생 배경
쉬운 설명
복잡한 개념을 실생활 비유로 설명합니다.
“집 인테리어의 4가지 도구”
*Container Queries* 는 *가구* — 같은 소파라도 거실에 두면 ㄱ자, 작은 방에 두면 1인용으로 모양이 자동 변형. *`:has()`* 는 *센서* — "방에 화분이 있으면 조명을 좀 더 밝게" 라는 규칙을 *방 자체* 에 단다. *Subgrid* 는 *모듈러 가구 시스템* — 카드 안의 선반들이 *옆 카드의 선반과 같은 높이* 로 자동 정렬. *Cascade Layers* 는 *층계 우선순위* — "1층은 바닥재(reset), 2층은 라이브러리, 3층은 우리 디자인" 식으로 층을 나눈 뒤, 같은 자리에 가구가 겹쳐도 *층 순서* 로 결정.
핵심 개념
Container Queries (`@container`)
컴포넌트가 *놓인 컨테이너의 크기* 에 따라 스타일 변경. 미디어 쿼리(뷰포트)와 직교 — *컴포넌트 단위 반응형*.
`:has()` 선택자
*"X 를 자손/자식으로 가지는 부모"* 를 선택. CSS 사상 첫 *부모/관계 셀렉터*. JS 의존을 줄임.
Subgrid
자식 grid 가 *부모 grid 의 트랙* 을 그대로 사용. 카드 안 제목·설명·CTA 가 *카드끼리* 정렬되는 패턴이 한 줄로 풀린다.
Cascade Layers (`@layer`)
CSS 에 *명시적 우선순위 그룹* 을 도입. 명시도(셀렉터 점수) 보다 *layer 순서* 가 먼저. *명시도 전쟁의 종결*.
| 도구 | 푸는 문제 | 대표 시나리오 | 안정성 (2026) |
|---|---|---|---|
| Container Queries | 컴포넌트 단위 반응형 | 같은 카드가 사이드바/메인에서 다른 모양 | ✅ 모든 메이저 |
| :has() | 부모/관계 셀렉터 부재 | 폼이 invalid 자식을 가지면 부모에 빨간 보더 | ✅ 모든 메이저 |
| Subgrid | 자식 격자 ↔ 부모 격자 정렬 | 카드 그리드의 항목 정렬 | ✅ 모든 메이저 |
| Cascade Layers | 명시도 전쟁 | 리셋·라이브러리·앱 스타일 우선순위 명시 | ✅ 모든 메이저 |
"4가지를 다 알아야 하나요" — 그렇다
디자인 시스템 코드 베이스가 *큰 회사일수록* 이 4가지가 *모두 자리를 잡고 있습니다*. 각자 푸는 문제가 다르고, *서로 대체* 가 되지 않습니다. Container Queries 가 미디어 쿼리를 대체하는 게 아니라 *직교 축* 인 것처럼, 4가지가 각자 영역에서 표준이 되었습니다.
실무 적용
어떤 상황에서 사용하는가
디자인 시스템에 카드/리스트/폼/모달이 있고, 같은 카드 컴포넌트가 사이드바·메인·모달 안 다 들어간다. 외부 헤드리스 라이브러리(Radix) 와 자체 스타일이 충돌해 명시도 헤킹이 누적된 상태.
어떻게 적용하는가
(1) *카드 컨테이너* (`.card-host`) 에 `container-type: inline-size`. 카드 내부는 `@container` 로 가로 480px 미만/이상에서 다른 레이아웃. (2) 카드 그리드는 `grid-template-rows: subgrid` 로 카드끼리 *제목·설명·CTA 행 정렬*. (3) 폼 검증은 `form:has(:invalid)` 로 부모 컨테이너 강조. *JS validate state* 동기화 코드 제거. (4) 글로벌 CSS 최상단에 `@layer reset, vendor, components, utilities;` 선언. Radix 같은 외부 라이브러리는 `@layer vendor` 안, 자체 디자인 시스템은 `@layer components`, Tailwind/유틸은 `@layer utilities`. (5) 기존 코드는 layer 밖에 *임시로* 두고 점진 이전. (6) Storybook + `@container` 의 *카드 부모 폭 조절 노브* 로 변형 시각화.
흔한 실수와 안티패턴
- *컨테이너 정의* 를 잊고 `@container` 만 작성 → 매칭 안 됨.
- `:has()` 셀렉터에 *광범위 와일드카드* 를 써서 셀렉터가 느려짐.
- Subgrid 자식이 *명시적 grid 컨테이너* 가 아니라 적용 안 됨.
- *!important* 가 layer 순서를 *역전* 시키는 사실을 모르고 디버깅 시간을 낭비.
- 구식 브라우저 지원이 필요한 서비스에서 폴백 없이 도입.
흔한 오해
"Container Queries 가 미디어 쿼리를 대체한다."
교정직교 축. 페이지 전체 레이아웃·내비 전환은 여전히 미디어 쿼리, *컴포넌트 단위* 는 컨테이너 쿼리.
왜 중요뷰포트가 의미 있는 결정점이 *여전히 존재* — 사이드바를 표시할지/숨길지 같은 결정.
":has() 는 매우 느려서 프로덕션에 못 쓴다."
교정브라우저 최적화로 일반적인 사용은 빠르다. *광범위 와일드카드* (`:has(*)`) 만 피하면 OK.
왜 중요브라우저 엔진이 :has() 매칭에 *증분 최적화* 를 쓴다. Chrome 의 측정에 따르면 일반 케이스는 무시 가능 비용.
"Subgrid 와 nested grid 는 같다."
교정다르다. Nested grid 는 *자식이 자기 grid 를 새로 정의*, Subgrid 는 *부모 grid 를 이어받음*. 후자만 부모 트랙 정렬 가능.
왜 중요Nested 는 격자가 분리되어 카드끼리 정렬이 안 된다.
"@layer 는 항상 *나중에 선언된* 게 강하다."
교정*일반* 규칙은 그렇지만, `!important` 끼리는 *먼저 선언된 layer 가 강함*.
왜 중요디자인 시스템(reset)이 앱의 `!important` override 를 다시 *최종 결정권* 으로 가져갈 수 있도록 설계됨.
면접 질문
답변 방향 힌트
"기준이 뷰포트 vs 부모 컨테이너" 를 출발점으로.
반드시 언급할 키워드
- 미디어 쿼리: *뷰포트* 기준, 페이지 전체 레이아웃에 적합
- 컨테이너 쿼리: *부모 컨테이너* 기준, 컴포넌트 단위 반응형
- `container-type: inline-size` 로 컨테이너 정의
- `@container` 로 자식 컴포넌트 스타일 분기
- `cqi`/`cqb` 컨테이너 단위로 폰트·간격까지 부드럽게
예상 꼬리 질문
- `container-type: size` 와 `inline-size` 의 차이와 *왜 inline-size 가 더 안전한지* 설명해 주세요.
- 컨테이너 쿼리 단위(`cqi`, `cqb`) 와 뷰포트 단위(`vw`, `vh`) 가 같이 등장할 때 어떤 기준으로 고르시겠습니까?
자기 점검
Container Queries 를 쓰려면 *반드시 부모에 추가해야 하는 속성* 한 가지는?
기대 키워드
자주 하는 오해
"@container 만 자식에 작성하면 된다" — 부모에 `container-type` 이 없으면 매칭이 일어나지 않는다.
Subgrid 와 nested grid 의 *결과 차이* 한 문장으로 답해보세요.
기대 키워드
자주 하는 오해
"둘 다 grid 안에 grid니까 같다" — nested 는 격자가 분리, subgrid 는 부모 격자를 이어받음.
`@layer reset, components, utilities;` 라고 선언했을 때, *layer 밖* 스타일과 layer 안 스타일이 충돌하면 누가 이기는가?
기대 키워드
자주 하는 오해
"id 셀렉터니까 layer 안의 id 가 이긴다" — layer 밖은 항상 모든 named layer 를 이긴다.
:has() 가 *느려질 수 있는* 셀렉터 패턴 한 가지를 답하라.
기대 키워드
자주 하는 오해
":has() 는 그냥 다 느리다" — 일반 케이스는 빠르고, 광범위 와일드카드만 위험.
학습 자료
- CSS Container Queries — MDNcontainer-type, @container, 컨테이너 단위(cqi/cqb).DocMDN Web Docs
- :has() — MDN관계 셀렉터의 정의·예시·성능 노트.DocMDN Web Docs
- CSS Subgrid — MDNsubgrid 의 정의와 카드/폼 정렬 사례.DocMDN Web Docs
- @layer — MDNCascade Layers 의 문법·우선순위·!important 동작.DocMDN Web Docs
- Cascade Layers Guide@layer 의 동기·도입 전략·실전 예시.BlogCSS-Tricks
- Cascade layers, subgrid, and container queries: What's new in CSS4 도구의 등장 시기와 사용 사례 정리.BlogLogRocket