반응형 디자인

반응형 디자인

반응형 페이지를 만들 때마다 미디어 쿼리를 일일이 써야 한다면 번거롭죠. Tailwind에선 모든 유틸리티를 브레이크포인트별로 조건부로 적용할 수 있어서, HTML을 벗어나지 않고 복잡한 반응형 UI를 만들 수 있어요. 이 글에서는 기본 브레이크포인트로 시작해, 커스텀 브레이크포인트와 컨테이너 쿼리까지 차근차근 설명할게요.

출처: Responsive design — Tailwind CSS 공식문서

기본 브레이크포인트 쓰기

먼저 문서 <head>에 viewport 메타 태그가 있는지 확인해요.

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

그 다음 유틸리티 앞에 브레이크포인트 이름과 :를 붙이면, 그 브레이크포인트 이상에서만 유틸리티가 적용돼요.

<img class="w-16 md:w-32 lg:w-48" src="..." />

기본 브레이크포인트는 5개예요. 기기 해상도에 맞춰 만들어져 있죠.

브레이크포인트 최소 너비 CSS
sm 40rem (640px) @media (width >= 40rem) { ... }
md 48rem (768px) @media (width >= 48rem) { ... }
lg 64rem (1024px) @media (width >= 64rem) { ... }
xl 80rem (1280px) @media (width >= 80rem) { ... }
2xl 96rem (1536px) @media (width >= 96rem) { ... }

(기본 브레이크포인트는 sm, md, lg, xl, 2xl 다섯 개이며, 공식 문서와 동일하게 확인해 주세요.)

이 방식이 강력한 이유는 프레임워크의 모든 유틸리티에 적용된다는 거예요. 자간 같은 미묘한 값조차 브레이크포인트별로 바꿀 수 있어요. 예를 들어 마케팅 페이지 카드처럼 작은 화면에선 세로로 쌓고, 큰 화면에선 가로로 배치하는 레이아웃은 이렇게 만들죠.

<div class="md:flex">
  <img class="md:shrink-0 md:h-full md:w-48" />
  <!-- ... -->
</div>

작은 화면에선 바깥 divdisplay: block이었다가 md:flex로 중간 이상에서 flex가 되고, 이미지가 줄어들지 않도록 md:shrink-0을, 폭과 높이를 md:h-full md:w-48로 고정하는 식이에요.

모바일 우선(mobile-first)

Tailwind는 모바일 우선 브레이크포인트 체계를 써요. 접두사 없는 유틸리티(예: uppercase)는 모든 화면에, 접두사 있는 유틸리티(예: md:uppercase)는 해당 브레이크포인트 이상에서 적용돼요. 그래서 모바일 레이아웃을 먼저 짜고, smmd 순서로 추가해 나가는 게 자연스러워요.

특정 구간만 타깃하기

md:flex는 기본적으로 md부터 계속 적용돼요. 특정 구간에만 적용하고 싶다면 반응형 변형자와 max-* 변형자를 쌓아요.

<div class="md:max-xl:flex"></div>

각 브레이크포인트마다 max-* 변형자가 기본 제공돼요 (max-sm, max-md, max-lg, max-xl, max-2xl). 특정 브레이크포인트 하나만 정확히 타깃할 땐 그 브레이크포인트와 다음 브레이크포인트의 max-*를 쌓으면 돼요.

<div class="md:max-lg:flex"></div>

커스텀 브레이크포인트

--breakpoint-* 테마 변수로 브레이크포인트를 원하는 대로 바꾸거나 추가할 수 있어요.

@import "tailwindcss";

@theme {
  --breakpoint-xs: 30rem;
  --breakpoint-2xl: 100rem;
  --breakpoint-3xl: 120rem;
}

이렇게 하면 2xl이 기본 96rem 대신 100rem이 되고, xs·3xl이 새로 생겨 마크업에서 쓸 수 있어요.

<div class="grid xs:grid-cols-2 3xl:grid-cols-6"></div>

기본 브레이크포인트가 rem을 쓰므로, 추가할 때도 rem으로 맞추는 걸 권장해요. 기본 브레이크포인트를 제거하려면 값을 initial로 리셋하면 되고, 전부 지우고 새로 정의할 땐 --breakpoint-*: initial; 후에 원하는 값을 정의하면 됩니다.

@theme {
  --breakpoint-*: initial;
  --breakpoint-tablet: 40rem;
  --breakpoint-laptop: 64rem;
}

컨테이너 쿼리

컨테이너 쿼리란

컨테이너 쿼리는 뷰포트 전체 크기가 아니라 부모 요소의 크기에 따라 스타일을 정하는 현대 CSS 기능이에요. 브레이크포인트 변형자처럼 모바일 우선이며, 대상 컨테이너 크기 이상에서 적용돼요.

기본 예시

@container로 컨테이너를 표시하고, @sm:*, @md:* 같은 변형자를 씁니다.

<div class="@container">
  <div class="flex flex-row @max-md:flex-col"></div>
</div>

이름 붙은 컨테이너

여러 컨테이너가 중첩된 복잡한 디자인에선 @container/{name}으로 이름을 붙이고, @sm/{name}처럼 특정 컨테이너를 타깃할 수 있어요.

<div class="@container/main">
  <div class="flex flex-row @sm/main:flex-col"></div>
</div>

커스텀 컨테이너 크기

--container-* 테마 변수로 컨테이너 쿼리 크기를 추가할 수 있어요. --container-8xl: 96rem;을 정의하면 8xl 컨테이너 쿼리 변형자가 생겨요. 1회성이면 @min-[475px]·@max-[960px] 같은 임의 값 변형자를 쓸 수도 있어요.

컨테이너 쿼리 단위

cqw, cqi 같은 컨테이너 쿼리 길이 단위를 다른 유틸리티의 임의 값으로 참조할 수 있어요.

<div class="@container">
  <div class="w-[50cqw]"></div>
</div>

cqb·cqh처럼 블록 크기가 필요한 단위를 쓸 땐 @container-size로 요소를 사이즈 컨테이너로 표시해야 전체 크기가 노출돼요.

기본 컨테이너 크기는 16rem(256px)부터 80rem(1280px)까지 단계별로 제공됩니다 (@3xs ~ @7xl).

더 알아보기 (Learn more)