🎨 Frontend CSS7. 반응형 (Media·Container)06 — Fluid Design (clamp·intrinsic)

06 — Fluid Design (clamp·intrinsic web design)

답하는 질문: 미디어 쿼리 없이 콘텐츠가 공간에 스스로 적응하게 할 수 있는가?


한 줄 답

가능하다 — clamp() + min()/max() + grid + minmax()의 조합이 콘텐츠 자체가 공간을 협상하게 한다. 이것이 Jen Simmons가 명명한 “Intrinsic Web Design”미디어 쿼리 기반의 적응(adaptive)이 아닌, 콘텐츠 기반의 적응(intrinsic). 브레이크포인트라는 이산적 점프 없이 연속적인 적응이 가능해진다.


Why — 브레이크포인트의 한계

1) RWD의 약속과 현실

2010년 Marcotte의 RWD는 연속 적응을 약속했지만, 실제 사이트들은 이산적 브레이크포인트 3~4개로 굳어졌다 — 320 / 768 / 1024 / 1440.

폭 →   320px  ┃  768px       ┃   1024px
              ┃               ┃
font: 14px    ┃→ 점프 → 16px ┃→ 점프 → 18px

브레이크포인트 사이적응 안 됨. 700px과 760px의 사용자 경험이 전혀 다른 사이트가 됐다.

2) Mike Riethmuller의 발견 (2015)

영국의 한 개발자가 “브레이크포인트 없이 폰트가 연속적으로 자라는 법” 을 트윗했다:

font-size: calc(16px + (24 - 16) * (100vw - 320px) / (1200 - 320));

이 공식이 Fluid Typography의 원형. 그러나 가독성 한계가 없어 극단 폭에서 폰트가 너무 작거나 너무 커졌다.

3) clamp()의 합류 (2020)

CSS Values Level 4의 clamp(min, preferred, max)Riethmuller의 트릭을 한 줄로 표현:

font-size: clamp(1rem, 1rem + 1vw, 1.5rem);

→ 최소 1rem 보장, 최대 1.5rem 제한, 그 사이는 vw에 비례하여 자연스럽게.

4) Jen Simmons의 명명 — Intrinsic Web Design (2018)

Mozilla의 Jen Simmons는 2018년 강연 “Everything You Know About Web Design Just Changed” 에서 새 패러다임을 정의했다:

패러다임도구결정 주체
Responsive (2010)media query디자이너가 폭별 분기
Adaptive (2012)sniffing서버가 디바이스 분기
Intrinsic (2018)grid + clamp콘텐츠가 공간 협상

“우리는 box를 그리지 않는다. 우리는 box가 어떻게 행동할지 가르친다.” — Jen Simmons


How — Intrinsic Web Design의 도구


What — 도구별 정확한 사양

1) clamp(MIN, PREFERRED, MAX)

  • MIN — 절대 하한. preferred가 이보다 작으면 MIN 사용.
  • PREFERRED — 이상적 값. 보통 vw 또는 cqi를 섞은 표현.
  • MAX — 절대 상한.
/* 폰트: 1.25rem ~ 2rem 사이, 폭 비례 */
h1 {
  font-size: clamp(1.25rem, 1rem + 2vw, 2rem);
}

해석:

  • 폭 0 → 1rem + 0 = 1rem → MIN 1.25rem이 이김.
  • 폭 1000px → 1rem + 20px ≈ 2.25rem → MAX 2rem이 이김.
  • 폭 400px → 1rem + 8px = 1.5rem → 그대로 사용.

2) min() / max()

/* 컨테이너 폭의 80% 또는 최대 1200px, 둘 중 작은 쪽 */
.container {
  width: min(80%, 1200px);
}
 
/* 절대 작아지지 않게 */
.touch-target {
  min-height: max(44px, 3rem);   /* 44px(접근성) 또는 3rem, 둘 중 큰 쪽 */
}

3) grid + minmax + auto-fit — 미디어 쿼리 0개 그리드

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: 1rem;
}

해석:

  • auto-fit — 트랙 수를 공간에 맞춰 자동 조정.
  • minmax(280px, 1fr) — 트랙 최소 280px, 최대 1fr(균등 분배).
  • min(100%, 280px)부모가 280px보다 좁을 때 트랙이 부모를 뚫지 않도록 보호.

한 줄로 1개부터 N개까지 적응. 320px 모바일 ~ 4K 모니터까지 미디어 쿼리 없음.

4) auto-fit vs auto-fill

  • auto-fit — 빈 트랙을 접어서 0으로 — 남은 항목이 늘어남.
  • auto-fill — 빈 트랙을 유지 — 항목이 고정 크기로 남음.
상황권장
카드 1개일 때 가운데 정렬, 폭 유지auto-fill
카드 1개일 때 공간 가득 차지auto-fit

5) Fluid Typography 공식

Utopia.fyi(Trys Mudford & James Gilyead, 2020)가 표준화한 패턴:

font-size: clamp(
  1rem,                                      /* 모바일 base */
  1rem + 0.5vw,                              /* 비례 항 */
  1.5rem                                     /* 데스크탑 max */
);

또는 Utopia 계산기로 typescale 전체를 클램프 식으로 생성. 한 번 정의하면 모든 폭에서 비례 유지.

6) aspect-ratio와 조합

.media {
  aspect-ratio: 16 / 9;
  width: min(100%, 800px);
}

→ 폭에 따라 높이가 비율 유지하며 자동 결정. 미디어 쿼리 불필요.

7) Container query 단위와 결합 (07-02 참조)

.card-title {
  font-size: clamp(1rem, 4cqi, 2rem);   /* 컨테이너 폭 4% */
}

→ 카드가 사이드바에 들어가면 작게, 본문에 들어가면 크게 — 컨테이너 기반 fluid.


What-if — 잘못 쓰면

Case 1: clamp의 PREFERRED가 줌(zoom)을 무시

font-size: clamp(1rem, 4vw, 2rem);   /* vw 사용 */

브라우저 줌 200%를 해도 vw뷰포트 기준이라 변하지 않음 → 사용자가 글자만 키우려는 요구를 무시. WCAG 1.4.4 위반 가능.

해결 — rem을 섞기:

font-size: clamp(1rem, 0.5rem + 2vw, 2rem);   /* rem 항이 줌에 반응 */

Case 2: auto-fit으로 카드 1개일 때 100% 차지

의도가 카드 폭 유지auto-fill을 써야 함.

Case 3: min(100%, 280px) 누락 시 트랙이 부모를 뚫음

grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));

→ 부모가 250px(예: 모바일 사이드바 안)이면 트랙이 부모를 뚫고 가로 스크롤 발생.

grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));

→ 부모가 좁으면 100%로 축소 — 안전.

Case 4: 너무 많은 clamp로 예측 불가능

.card {
  padding: clamp(0.5rem, 2cqi, 1.5rem);
  gap: clamp(0.25rem, 1cqi, 0.75rem);
  border-radius: clamp(4px, 1cqi, 12px);
  font-size: clamp(0.875rem, 3cqi, 1.125rem);
}

→ 모든 값이 동시에 변하면 디버깅 어려움. typescale을 토큰화하고 클램프는 한 곳에서 관리:

:root {
  --fs-step-0: clamp(1rem, 0.5rem + 1vw, 1.25rem);
}

Case 5: 비례 항이 음수가 되는 경우

font-size: clamp(1rem, -0.5rem + 4vw, 2rem);   /* 작은 폭에서 음수 가능 */

음수가 되면 MIN으로 클램프 — 동작은 안전하지만 극단 폭에서 갑작스러운 점프가 보일 수 있음. 비례 항을 항상 양수가 되도록 설계 권장.


Insight — Intrinsic은 디자인 사고의 전환

전통 디자인은 고정 그리드에서 출발했다 — 인쇄·그래픽 디자인의 유산. 12-column grid, Bootstrap, 960.gs.

Intrinsic Web Design은 그 반대로 출발한다 — 콘텐츠가 먼저, 그리드는 그 다음. 디자이너는 콘텐츠가 어떻게 행동해야 하는지를 정의하고, 그리드는 그 행동을 허용하는 캔버스가 된다.

Jen Simmons의 2018 강연에서 가장 인용되는 문장:

“We’re not designing pages. We’re designing systems of components that respond to their environment.”

이는 단순히 새 CSS 기능의 묶음이 아니라 디자이너-개발자 사고의 분기점.

Container Queries, :has(), @scope, intrinsic units — 이 모든 것이 한 방향을 가리킨다: 컴포넌트가 자기 환경을 스스로 협상하게 하라.

브레이크포인트 디자인이 “이 폭에서 이 모습” 을 정의한다면, intrinsic 디자인은 “이 콘텐츠는 이렇게 행동하라” 를 정의한다. 후자가 훨씬 적은 코드로 훨씬 많은 폭을 커버한다.


요약 + Mermaid

  • clamp(min, preferred, max)연속 적응 — 브레이크포인트 없이.
  • grid + minmax + auto-fit + min(100%, ...) 한 줄로 카드 그리드 완성.
  • Intrinsic Web Design(Jen Simmons) — 콘텐츠가 공간을 협상.
  • clamprem을 섞어 줌 접근성 보장.
  • 너무 많은 clamp는 토큰화로 관리.

다음: 07-mobile-first — 전략과 역사.