🎨 Frontend CSS7. 반응형 (Media·Container)📖 개요

07 — 반응형 (Responsive)

이 챕터가 답하는 질문: 반응형이란 디바이스에 적응하는 것이 아니라 컨텍스트에 적응하는 것이다. 그렇다면 컨텍스트는 어디서 오는가?


한 줄 답 (Pyramid Top)

반응형 CSS는 5개의 컨텍스트 축에 반응한다 — ① 뷰포트(@media) ② 부모 컨테이너(@container) ③ 자식 존재(:has()) ④ DOM 범위(@scope) ⑤ 사용자 환경(prefers-*, dvh). 디바이스가 아니라 컨텍스트다. 같은 컴포넌트가 사이드바에서 좁게, 본문에서 넓게 — 뷰포트가 아니라 컨테이너가 결정하는 시대가 되었다.


Why — 왜 반응형이 필요한가

1) 역사적 출발: 2010년 Ethan Marcotte

2010년 5월 25일, A List Apart에 발표된 한 편의 글이 웹 디자인을 갈라놓았다 — Ethan Marcotte의 “Responsive Web Design”. 그 글의 핵심 주장:

“우리는 디바이스마다 다른 사이트를 만들 수 없다. 하나의 사이트가 모든 디바이스에 적응해야 한다.”

세 가지 도구를 묶었다 — Fluid Grid + Flexible Images + Media Queries. 이전까지 우리는 m.example.com 같은 별도 모바일 사이트를 만들었다.

2) 그러나 14년 동안 풀리지 않은 한계

  • 뷰포트만 본다: 같은 카드를 사이드바·본문에 넣어도 뷰포트가 같으면 같은 스타일. 컴포넌트 단위 반응이 불가능했다.
  • 부모를 모른다: CSS는 자식만 선택할 수 있었다. 자식의 존재 여부로 부모 스타일을 바꿀 수 없었다.
  • 격리가 없다: 컴포넌트의 스타일이 트리 전체로 새어 나갔다 — BEM, CSS Modules 같은 우회로 해결했다.
  • 뷰포트 단위가 거짓말: iOS Safari의 100vh는 주소창을 포함한 최대 높이 — 실제 보이는 영역보다 컸다.

3) 2022~2024년의 합류 — 4가지 신무기

신무기표준화해결한 문제
@container2023 Baseline”뷰포트가 아니라 부모”에 반응
:has()2023 Baseline부모 선택자 — 자식의 존재로 부모를 선택
@scope2024 Chrome/Safari, Firefox 미지원컴포넌트 스타일 격리
dvh/svh/lvh2023 Baseline동적 뷰포트 높이 — iOS 주소창 문제 해결

14년 만에 반응형의 정의가 뷰포트 반응에서 컨텍스트 반응으로 확장되었다.


How — 어떻게 정리했나

이 챕터는 반응형의 5개 축을 작은 것에서 큰 것으로 — 부분 → 전체의 순서로 다룬다.

#파일다루는 것핵심 키워드
101-media-queries@media 전체, range syntax, prefers-*width, hover, pointer, prefers-color-scheme
202-container-queries@container, container-type, cqi/cqw/cqbcontainer-type, inline-size, cqi
303-has-selector:has() 부모 선택자 패턴:has, parent-aware, sibling-based
404-scope@scope, donut scope, nesting과 결합@scope, donut, scoped
505-viewport-unitsdvh/svh/lvh, iOS Safari 이슈dvh, svh, lvh, dynamic viewport
606-fluid-designclamp(), fluid grid, intrinsic web designclamp, minmax, fluid type, Jen Simmons
707-mobile-first모바일/데스크탑 퍼스트, 브레이크포인트 전략mobile-first, RWD, breakpoint

What — 이 챕터의 범위

  • CSS Conditional Rules Module Level 3/4@media, @supports, range syntax
  • CSS Containment Module Level 3@container, container-type, container-name
  • Selectors Level 4:has(), :is(), :where()
  • CSS Cascading and Inheritance Level 6@scope
  • CSS Values and Units Level 4dvh/svh/lvh, cqi/cqw/cqb, clamp()
  • CSS Media Queries Level 5prefers-color-scheme, prefers-reduced-motion, hover, pointer

브라우저 호환성은 Baseline 2024 기준 — @scope는 Firefox 미지원(2026-05 기준 진행 중).


What-if — 잘못 쓰면

증상원인해결
컨테이너 쿼리가 동작 안 함container-type 미지정 — 기본 normal은 쿼리 대상 아님부모에 container-type: inline-size
@container (height > 400px) 무시됨inline-size는 인라인 축만 — 높이 쿼리는 size 필요container-type: size + layout containment 비용 인지
iOS Safari에서 100vh가 잘림vh최대 뷰포트(주소창 숨김 가정)100dvh(동적) 또는 100svh(작은쪽)
:has() 사용 후 리렌더 jank매 DOM 변경마다 재평가, 큰 트리에서 비싸짐범위를 좁히기 — .card:has(...) 식으로 앵커 명시
Firefox에서 @scope 무시2026-05 기준 Firefox 미지원@supports (at-rule: @scope) 가드, 폴백 BEM/CSS Modules
데스크탑에서 작업 후 모바일이 깨짐데스크탑 퍼스트 — max-width 사슬이 길어짐모바일 퍼스트로 전환, min-width만 사용

Insight — “디바이스 → 컨텍스트”의 14년

2010년의 RWD는 하나의 적과 싸웠다 — 디바이스 파편화. iPhone 320px, iPad 768px, Desktop 1024px.

그러나 2024년의 적은 다르다 — 컴포넌트 재사용성. 같은 카드 컴포넌트가 사이드바(280px), 본문(680px), 풀폭(1200px)에서 다르게 보여야 한다. 뷰포트는 같다.

이 변화를 3개의 키워드로 압축할 수 있다.

  1. From device to context (디바이스 → 컨텍스트)@container
  2. From child to parent (자식 → 부모):has()
  3. From global to local (전역 → 지역)@scope

Jen Simmons는 2018년 강연 “Everything You Know About Web Design Just Changed” 에서 이를 Intrinsic Web Design이라고 명명했다. 그녀의 정의:

“미디어 쿼리에 의존하지 않고, grid + minmax + clamp로 콘텐츠 자체가 공간에 적응하도록 두는 디자인.”

이 챕터의 6번 문서(06-fluid-design)가 그 철학을 코드로 옮긴다.


요약 + Mermaid

  • 반응형은 디바이스가 아니라 컨텍스트에 적응한다.
  • 5개 축 — 뷰포트 / 컨테이너 / 부모(:has) / 범위(@scope) / 사용자 환경(prefers-*).
  • dvh/svh/lvh로 iOS Safari 100vh 잘림 문제 해결.
  • Intrinsic Web Designclamp + grid + minmax로 미디어 쿼리 없이 적응.
  • 2010년 RWD → 2024년 컨텍스트 적응, 14년 진화.

다음: 01-media-queries부터 순서대로.