01 Tailwind CSS
Tailwind CSS
보통 웹사이트를 꾸밀 때는 별도의 CSS 파일에 코드를 길게 작성해야 한다. 하지만 Tailwind는 **“이미 만들어진 태그(Class)“**를 HTML에 바로 붙여서 디자인하는 방식이다.
테일윈드 공식
테일윈드 치트시트
공식테일윈드 피그마 스타일파일
테일윈드 디자인토큰 생성기 피그마 플러그인
1. Basics — 설치
NPM 설치 (Vite 기준)
- 터미널에 아래 명령어 입력
1npm install tailwindcss @tailwindcss/vite- vite.config.js 파일에 아래 코드 추가
1import { defineConfig } from 'vite'2import react from '@vitejs/plugin-react'3import tailwindcss from '@tailwindcss/vite' // ← 추가4
5export default defineConfig({6 plugins: [react(), tailwindcss()],7})- src/index.css 에 아래 코드 추가
1@import "tailwindcss";CDN 설치
HTML의 <head> 태그 안에 아래 코드를 삽입한다.
1<!DOCTYPE html>2<html>3<head>4 <meta charset="UTF-8">5 <meta name="viewport" content="width=device-width, initial-scale=1.0">6 <script src="https://unpkg.com/@tailwindcss/browser@4"></script>7</head>8<body>9 <h1 class="text-3xl font-bold text-blue-600 underline">10 Hello, Tailwind!11 </h1>12</body>13</html>요약
유틸리티 우선(Utility-First)
- 기존 방식:
.btn { background: blue; }클래스를 정의하고 HTML에서 적용한다. - Tailwind 방식:
class="bg-blue-500 text-white"와 같이 이미 정의된 클래스를 조합한다.
2. Sizing
2.1. Width
| 클래스 | 값 |
|---|---|
w-{n} | spacing 스케일 (w-4 = 16px) |
w-full | 100% |
w-screen | 100vw |
w-auto | auto |
w-1/2, w-1/3, w-2/3 | 50%, 33.3%, 66.6% |
w-1/4, w-3/4 | 25%, 75% |
w-[200px] | 임의값 |
min-w-0, min-w-full | 최솟값 |
max-w-sm ~ max-w-7xl | 최댓값 (sm=24rem~) |
2.2. Height
| 클래스 | 값 |
|---|---|
h-{n} | spacing 스케일 |
h-full | 100% |
h-screen | 100vh |
h-auto | auto |
min-h-screen | min-height: 100vh |
min-h-0 | min-height: 0 |
h-dvh | 100dvh (동적 뷰포트) |
h-svh | 100svh (소형 뷰포트) |
2.3. size 단축 클래스
| 클래스 | 값 |
|---|---|
size-10 | w-10 h-10 |
size-[200px] | w-200px h-200px |
1// 1단계: w-full, h-16 — 고정 크기2<div className="w-full">가로 100%</div>3<div className="h-16">높이 64px</div>1// 2단계: 비율 — 부모 기준 백분율2<div className="w-1/2">부모의 50%</div>3<div className="w-1/3">부모의 33%</div>4<div className="w-2/3">부모의 66%</div>1// 3단계: max-w — 최대 너비 제한 (반응형에 자주 사용)2<div className="w-full max-w-xl">최대 576px까지만</div>3<div className="w-full max-w-4xl mx-auto">최대 너비 + 가운데 정렬</div>1// 4단계: size — 가로·세로 동시 지정2<div className="size-10">40x40</div>3<div className="size-16">64x64</div>4<div className="size-[200px]">200x200</div>3. Typography — 타이포그래피
3.1. Font Size (text-*)
| 클래스 | 크기 | line-height |
|---|---|---|
text-xs | 12px | 1rem |
text-sm | 14px | 1.25rem |
text-base | 16px | 1.5rem |
text-lg | 18px | 1.75rem |
text-xl | 20px | 1.75rem |
text-2xl | 24px | 2rem |
text-3xl | 30px | 2.25rem |
text-4xl | 36px | 2.5rem |
text-5xl | 48px | 1 |
text-6xl | 60px | 1 |
3.2. Font Weight
1font-thin /* 100 */2font-extralight /* 200 */3font-light /* 300 */4font-normal /* 400 */5font-medium /* 500 */6font-semibold /* 600 */7font-bold /* 700 */8font-extrabold /* 800 */9font-black /* 900 */3.3. Text 색상
1text-white text-black2text-gray-500 text-gray-9003text-yellow-300 text-yellow-4004text-blue-600 text-red-5005text-white/80 /* 투명도 포함 */3.4. Text 정렬 · 변환 · 장식
1/* 정렬 */2text-left text-center text-right text-justify3
4/* 변환 */5uppercase lowercase capitalize normal-case6
7/* 장식 */8underline line-through no-underline overline9
10/* 오버플로 처리 */11truncate /* 한 줄 말줄임 */12line-clamp-2 /* 2줄 말줄임 */13line-clamp-3 /* 3줄 말줄임 */14whitespace-nowrap /* 줄바꿈 금지 */3.5. Letter Spacing · Line Height
1/* 자간 */2tracking-tight tracking-normal tracking-wide tracking-widest3
4/* 행간 */5leading-none /* 1 */6leading-tight /* 1.25 */7leading-normal /* 1.5 */8leading-loose /* 2 */9leading-[1.8] /* 임의값 */1// 1단계: text-size — 글자 크기2<p className="text-sm">작은 텍스트 (14px)</p>3<p className="text-base">기본 텍스트 (16px)</p>4<p className="text-xl">큰 텍스트 (20px)</p>5<p className="text-4xl">제목용 텍스트 (36px)</p>1// 2단계: font-weight — 굵기2<p className="font-normal">일반 굵기</p>3<p className="font-bold">굵게</p>4<p className="font-black">가장 굵게</p>1// 3단계: text-color — 색상2<p className="text-white">흰색</p>3<p className="text-gray-400">회색</p>4<p className="text-yellow-400">노란색</p>1// 4단계: text-align — 정렬2<p className="text-left">왼쪽 정렬</p>3<p className="text-center">가운데 정렬</p>4<p className="text-right">오른쪽 정렬</p>1// 5단계: truncate / line-clamp — 넘치는 텍스트 처리2<p className="truncate">한 줄을 넘으면 말줄임표로 잘림...</p>3<p className="line-clamp-2">두 줄을 넘으면 잘림. 긴 텍스트 긴 텍스트 긴 텍스트 긴 텍스트...</p>4. Backgrounds — 배경
4.1. 기본 색상 팔레트
Tailwind의 색상은 색상명-숫자 형태이다. 숫자가 클수록 어두워진다 (50 가장 밝음, 950 가장 어두움).
| 색상명 | 대표 클래스 예시 |
|---|---|
| slate, gray, zinc, neutral, stone | 무채색 계열 |
| red, orange, amber, yellow | 따뜻한 계열 |
| lime, green, emerald, teal | 초록 계열 |
| cyan, sky, blue, indigo | 파란 계열 |
| violet, purple, fuchsia, pink, rose | 보라·분홍 계열 |
4.2. 배경색 적용
1/* 배경색 */2bg-white bg-black3bg-gray-900 bg-gray-8004bg-yellow-400 bg-blue-6005
6/* 투명도 (슬래시 문법) */7bg-black/50 /* background: rgba(0,0,0,0.5) */8bg-white/10 /* background: rgba(255,255,255,0.1) */9bg-black/90 /* GOFLIX 헤더에 사용 */4.3. 테두리 색상
1border-gray-200 border-yellow-400 border-transparent1// 1단계: bg-color — 단색 배경2<div className="bg-black">검은 배경</div>3<div className="bg-gray-800">어두운 회색 배경</div>4<div className="bg-yellow-400">노란 배경</div>1// 2단계: bg-color + text-color — 배경과 텍스트 색상 함께2<div className="bg-gray-900 text-white">어두운 배경에 흰 텍스트</div>3<div className="bg-yellow-400 text-black">노란 배경에 검은 텍스트</div>1// 3단계: bg-color/투명도 — 슬래시로 불투명도 조절2<div className="bg-black/50">50% 투명한 검은 배경</div>3<div className="bg-black/90">90% 불투명한 검은 배경</div>1// 4단계: bg-gradient — 그라디언트 배경2<div className="bg-gradient-to-r from-black to-gray-800">좌 → 우</div>3<div className="bg-gradient-to-t from-black to-transparent">아래 → 위(투명)</div>5. Borders — 테두리 & Ring
5.1. Border Width · Color · Style
1<!-- 기본 테두리 -->2<div class="border border-gray-200">1px 테두리</div>3<div class="border-2 border-blue-500">2px 파란 테두리</div>4<div class="border-4 border-dashed border-red-400">4px 점선</div>5
6<!-- 방향별 테두리 -->7<div class="border-b border-gray-200">하단만</div>8<div class="border-t-2 border-l-2 border-blue-300">상단+좌측</div>9
10<!-- 모서리 반지름 -->11<div class="rounded-sm">약간</div>12<div class="rounded-lg">중간</div>13<div class="rounded-2xl">큰 (카드)</div>14<div class="rounded-full">원형</div>1: border — 기본 1px 회색 테두리
2: border-2 — 2px, border-blue-500 — 파란색
3: border-dashed — 점선 스타일
5: border-b — 아래쪽만, border-t-2 border-l-2 — 위쪽과 왼쪽 2px
9~12: rounded-* — 모서리 반지름 (sm < lg < 2xl, full=50%)
18. GOFLIX 프로젝트 적용 예시
Tailwind로 영화 정보 사이트를 만드는 실전 예시입니다.
18.1. Header 분석
1<header className="fixed top-0 left-0 w-full py-4 px-2 bg-black/90 z-50">2 {/* fixed: 스크롤해도 고정 */}3 {/* top-0 left-0: 화면 최상단 좌측 */}4 {/* w-full: 전체 너비 */}5 {/* py-4 px-2: 상하 16px, 좌우 8px 패딩 */}6 {/* bg-black/90: 검은색 배경 90% 불투명 */}7 {/* z-50: 다른 요소 위에 표시 */}8 <div className="container mx-auto">9 <Link to="/">10 <h1 className="text-3xl text-yellow-300 font-bold">11 {/* text-3xl: 30px 텍스트 */}12 {/* text-yellow-300: 연한 노란색 */}13 {/* font-bold: 굵은 글씨 */}14 GOFLIX15 </h1>16 </Link>17 </div>18</header>18.2. 영화 카드 컴포넌트 패턴
1function MovieCard({ movie }) {2 return (3 <div className="group relative rounded-lg overflow-hidden cursor-pointer4 transition-transform duration-300 hover:scale-1055 shadow-lg hover:shadow-yellow-400/30">6 {/* 포스터 이미지 */}7 <img8 src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}9 alt={movie.title}10 className="w-full aspect-[2/3] object-cover"11 />12 {/* 호버 오버레이 */}13 <div className="absolute inset-0 bg-black/70 opacity-0 group-hover:opacity-10014 transition-opacity duration-300 flex flex-col justify-end p-4">15 <h3 className="text-white font-bold text-sm line-clamp-2">{movie.title}</h3>16 <p className="text-yellow-300 text-xs mt-1">⭐ {movie.vote_average.toFixed(1)}</p>17 </div>18 </div>19 );20}18.3. 전체 페이지 레이아웃
1// App.jsx2<main className="bg-black text-white min-h-screen pt-16">3 {/* bg-black: 검은 배경 */}4 {/* text-white: 기본 텍스트 흰색 */}5 {/* min-h-screen: 최소 전체 높이 */}6 {/* pt-16: 상단 64px (fixed 헤더 높이만큼) */}7 <Outlet />8</main>9
10// 홈 페이지11<section className="container mx-auto px-4 py-8">12 <h2 className="text-2xl font-bold mb-6 text-yellow-300">인기 영화</h2>13 <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4">14 {movies.map(movie => <MovieCard key={movie.id} movie={movie} />)}15 </div>16</section>18.4. 버튼 스타일 패턴
1{/* 주요 액션 버튼 */}2<button className="bg-yellow-400 text-black font-bold px-6 py-2 rounded-lg3 hover:bg-yellow-300 active:scale-954 transition-all duration-200 cursor-pointer">5 자세히 보기6</button>7
8{/* 보조 버튼 (아웃라인) */}9<button className="border-2 border-white text-white font-semibold px-6 py-2 rounded-lg10 hover:bg-white hover:text-black11 transition-all duration-200 cursor-pointer">12 목록 추가13</button>18.5. 영화 상세 페이지
1function MovieDetail({ movie }) {2 return (3 <div className="relative min-h-screen bg-black text-white">4 {/* 배경 이미지 */}5 <div className="relative h-[60vh]">6 <img7 src={`https://image.tmdb.org/t/p/original${movie.backdrop_path}`}8 className="w-full h-full object-cover"9 />10 <div className="absolute inset-0 bg-gradient-to-t from-black via-black/40 to-transparent" />11 </div>12
13 {/* 콘텐츠 */}14 <div className="container mx-auto px-4 -mt-32 relative z-10">15 <div className="flex flex-col md:flex-row gap-8">16 <img17 src={`https://image.tmdb.org/t/p/w300${movie.poster_path}`}18 className="w-40 md:w-56 rounded-xl shadow-2xl flex-none mx-auto md:mx-0"19 />20 <div className="flex-1">21 <h1 className="text-3xl md:text-5xl font-black">{movie.title}</h1>22 <div className="flex items-center gap-3 mt-3 text-sm text-gray-400">23 <span className="text-yellow-400 font-bold">⭐ {movie.vote_average.toFixed(1)}</span>24 <span>{movie.release_date.slice(0, 4)}</span>25 </div>26 <p className="mt-4 text-gray-300 leading-relaxed max-w-2xl line-clamp-4 md:line-clamp-none">27 {movie.overview}28 </p>29 <div className="flex gap-3 mt-6">30 <button className="bg-yellow-400 text-black font-bold px-6 py-3 rounded-lg31 hover:bg-yellow-300 active:scale-95 transition-all duration-200">32 ▶ 재생33 </button>34 <button className="border border-white/40 text-white px-6 py-3 rounded-lg35 hover:bg-white/10 transition-all duration-200">36 + 내 목록37 </button>38 </div>39 </div>40 </div>41 </div>42 </div>43 )44}요약
클래스 조합 팁
복잡한 컴포넌트는 관심사별로 줄을 나눠 읽기 좋게 작성한다.
레이아웃 → 크기 → 색상 → 상태 순으로 배치하면 유지보수가 편하다.
주의
자주 하는 실수
hover:scale-105만 쓰면 애니메이션이 없음 →transition-transform duration-300필수opacity-0 group-hover:opacity-100을 쓸 때 부모에group클래스 빠뜨리지 않기fixed헤더가 있으면 main에pt-{헤더높이}필수 (겹침 방지)
6. Layout — 레이아웃 (Display · Position)
6.1. Display
| 클래스 | CSS | 설명 |
|---|---|---|
block | display: block | 블록 요소 |
inline | display: inline | 인라인 요소 |
inline-block | display: inline-block | 인라인 블록 |
flex | display: flex | 플렉스 컨테이너 |
inline-flex | display: inline-flex | 인라인 플렉스 |
grid | display: grid | 그리드 컨테이너 |
hidden | display: none | 숨김 |
1<div className="block">block — 한 줄 전체를 차지</div>2<span className="inline">inline — 내용 크기만큼, 줄바꿈 없음</span>3<span className="inline-block">inline-block — 줄바꿈 없이 나란히</span>4<div className="hidden">hidden — 화면에서 완전히 사라짐</div>6.2. Position
| 클래스 | CSS |
|---|---|
static | position: static |
relative | position: relative |
absolute | position: absolute |
fixed | position: fixed |
sticky | position: sticky |
6.3. 위치 지정 (inset)
| 클래스 | 의미 |
|---|---|
top-0 | 위에서 0 |
left-0 | 왼쪽에서 0 |
inset-0 | 상하좌우 모두 0 |
inset-x-0 | 좌우만 0 |
inset-y-0 | 상하만 0 |
1// 1단계: relative — 자식의 기준점 역할2<div className="relative">3 기준이 되는 부모4</div>1// 2단계: absolute + top/left — 부모 기준으로 위치 지정2<div className="relative">3 <div className="absolute top-0 left-0">왼쪽 위에 배치</div>4 <div className="absolute top-0 right-0">오른쪽 위에 배치</div>5</div>1// 3단계: inset-0 — 부모 전체를 꽉 채움2<div className="relative">3 <div className="absolute inset-0">부모 전체 크기로 채움</div>4</div>1// 4단계: fixed — 스크롤해도 화면에 고정2<header className="fixed top-0 left-0">스크롤해도 고정되는 헤더</header>1// 5단계: sticky — 스크롤 시 특정 위치에 달라붙음2<h2 className="sticky top-0">스크롤하면 상단에 고정되는 제목</h2>6.4. z-index
1// 숫자가 클수록 위에 표시됨2<div className="z-0">맨 아래</div>3<div className="z-10">그 위</div>4<div className="z-50">가장 위</div>7. Flexbox
가장 많이 쓰는 레이아웃 방식. 방향, 줄바꿈, 자식 크기를 클래스 조합으로 제어한다.
7.1. 방향 (flex-direction)
| 클래스 | CSS |
|---|---|
flex-row | flex-direction: row (기본값) |
flex-row-reverse | flex-direction: row-reverse |
flex-col | flex-direction: column |
flex-col-reverse | flex-direction: column-reverse |
7.2. 줄바꿈 · 자식 크기
1/* 줄바꿈 */2flex-wrap flex-nowrap flex-wrap-reverse3
4/* 자식 요소 크기 제어 */5flex-1 /* flex: 1 1 0% — 공간을 균등 분할 */6flex-auto /* flex: 1 1 auto */7flex-none /* flex: none — 크기 고정 */8
9/* 개별 크기 */10grow /* flex-grow: 1 */11grow-0 /* flex-grow: 0 */12shrink /* flex-shrink: 1 */13shrink-0 /* flex-shrink: 0 */1// 1단계: flex — 자식을 가로로 나열2<div className="flex">3 <div>아이템 1</div>4 <div>아이템 2</div>5 <div>아이템 3</div>6</div>1// 2단계: flex-col — 세로로 나열2<div className="flex flex-col">3 <div>위</div>4 <div>중간</div>5 <div>아래</div>6</div>1// 3단계: gap — 자식 사이 간격2<div className="flex gap-4">3 <div>아이템 1</div>4 <div>아이템 2</div>5 <div>아이템 3</div>6</div>1// 4단계: flex-1 / flex-none — 자식 크기 제어2<div className="flex">3 <div className="flex-none">고정 크기</div>4 <div className="flex-1">남은 공간을 모두 차지</div>5</div>1// 5단계: flex-wrap — 넘치면 줄바꿈2<div className="flex flex-wrap gap-2">3 <div>태그 1</div>4 <div>태그 2</div>5 <div>태그 3</div>6 <div>태그 4</div>7 <div>태그 5</div>8</div>7.3. Container
container는 화면 크기에 따라 max-width를 자동으로 맞춰주는 클래스다. 단독으로는 왼쪽 정렬이므로, mx-auto를 함께 써서 가운데 정렬한다.
| 브레이크포인트 | 적용되는 max-width |
|---|---|
| 기본 (모바일) | 100% |
| sm (640px~) | 640px |
| md (768px~) | 768px |
| lg (1024px~) | 1024px |
| xl (1280px~) | 1280px |
| 2xl (1536px~) | 1536px |
1// 1단계: container 기본 — 반응형 max-width 자동 적용2<div className="container">콘텐츠</div>1// 2단계: mx-auto 추가 — 가운데 정렬2<div className="container mx-auto">콘텐츠</div>1// 3단계: 실전 — 페이지 전체 레이아웃에 적용2<main>3 <section className="container mx-auto">4 <h2>인기 영화</h2>5 ...6 </section>7
8 <section className="container mx-auto">9 <h2>최신 영화</h2>10 ...11 </section>12</main>8. Grid
2차원 레이아웃. 영화 카드 목록처럼 열을 고정하거나 반응형으로 배치할 때 사용한다.
8.1. 열(Column) 정의
| 클래스 | CSS |
|---|---|
grid-cols-1 | grid-template-columns: repeat(1, 1fr) |
grid-cols-2 ~ 12 | 2~12 등분 |
grid-cols-none | 컬럼 정의 없음 |
grid-cols-[200px_1fr] | 임의값 지정 |
8.2. 간격
1gap-4 /* row-gap + column-gap: 1rem */2gap-x-6 /* column-gap: 1.5rem */3gap-y-4 /* row-gap: 1rem */8.3. 자식 요소 병합 (span)
1col-span-2 /* 열 2칸 차지 */2col-span-full /* 전체 열 차지 */3row-span-2 /* 행 2칸 차지 */1// 1단계: grid + grid-cols — 열 개수 지정2<div className="grid grid-cols-3">3 <div>1</div>4 <div>2</div>5 <div>3</div>6 <div>4</div>7 <div>5</div>8 <div>6</div>9</div>1// 2단계: gap — 셀 사이 간격 추가2<div className="grid grid-cols-3 gap-4">3 <div>1</div>4 <div>2</div>5 <div>3</div>6</div>1// 3단계: col-span — 특정 셀이 여러 칸을 차지2<div className="grid grid-cols-3 gap-4">3 <div className="col-span-2">넓은 셀 (2칸)</div>4 <div>1칸</div>5 <div>1칸</div>6 <div className="col-span-full">전체 너비 셀</div>7</div>1// 4단계: 반응형 — 화면 크기에 따라 열 수 변경2<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">3 {movies.map(movie => (4 <MovieCard key={movie.id} movie={movie} />5 ))}6</div>9. Alignment — 정렬 (Justify · Align)
Flexbox와 Grid에서 아이템을 정렬하는 유틸리티이다.
9.1. 주축 정렬 (justify-content)
| 클래스 | CSS |
|---|---|
justify-start | justify-content: flex-start |
justify-center | justify-content: center |
justify-end | justify-content: flex-end |
justify-between | justify-content: space-between |
justify-around | justify-content: space-around |
justify-evenly | justify-content: space-evenly |
9.2. 교차축 정렬 (align-items)
| 클래스 | CSS |
|---|---|
items-start | align-items: flex-start |
items-center | align-items: center |
items-end | align-items: flex-end |
items-stretch | align-items: stretch |
items-baseline | align-items: baseline |
9.3. Grid 정렬
1place-items-center /* align-items + justify-items: center */2place-content-center1// 1단계: justify-center — 가로 중앙 정렬2<div className="flex justify-center">3 <div>가운데 배치됨</div>4</div>1// 2단계: justify-between — 양 끝으로 배치2<div className="flex justify-between">3 <div>왼쪽</div>4 <div>오른쪽</div>5</div>1// 3단계: items-center — 세로 중앙 정렬2<div className="flex items-center">3 <div>세로 중앙에 배치됨</div>4</div>1// 4단계: justify + items 조합 — 완전 중앙2<div className="flex justify-center items-center">3 <div>정중앙에 배치됨</div>4</div>1// 5단계: place-items-center — grid에서 셀 안 정중앙2<div className="grid grid-cols-3 place-items-center">3 <div>★</div>4 <div>★</div>5 <div>★</div>6</div>10. Spacing — 간격 (Margin · Padding · Gap)
기본 단위: 1 = 4px (0.25rem). 4 = 16px, 8 = 32px처럼 4배수로 계산한다.
10.1. Margin
| 클래스 | 방향 | 예시 |
|---|---|---|
m-{n} | 전체 | m-4 → 16px 사방 |
mx-{n} | 좌우 | mx-auto → 가운데 정렬 |
my-{n} | 상하 | my-8 |
mt-{n} | 위 | mt-16 |
mr-{n} | 오른쪽 | |
mb-{n} | 아래 | |
ml-{n} | 왼쪽 | |
-m-{n} | 음수 마진 | -mt-4 |
10.2. Padding (같은 패턴)
1p-4 px-6 py-3 pt-2 pr-4 pb-6 pl-210.3. 자주 쓰는 값 참고표
| 클래스 숫자 | rem | px |
|---|---|---|
| 1 | 0.25rem | 4px |
| 2 | 0.5rem | 8px |
| 3 | 0.75rem | 12px |
| 4 | 1rem | 16px |
| 5 | 1.25rem | 20px |
| 6 | 1.5rem | 24px |
| 8 | 2rem | 32px |
| 10 | 2.5rem | 40px |
| 12 | 3rem | 48px |
| 16 | 4rem | 64px |
| 20 | 5rem | 80px |
| 24 | 6rem | 96px |
1// 1단계: p — 사방 패딩2<div className="p-4">사방 16px 여백</div>3<div className="p-8">사방 32px 여백</div>1// 2단계: px / py — 방향별 패딩2<div className="px-6">좌우만 24px</div>3<div className="py-3">상하만 12px</div>4<div className="px-6 py-3">좌우 24px + 상하 12px</div>1// 3단계: mt / mb — 위아래 마진2<div className="mt-8">위에 32px 여백</div>3<div className="mb-4">아래에 16px 여백</div>1// 4단계: mx-auto — 가운데 정렬2<div className="mx-auto">가운데 정렬</div>1// 5단계: space-y — 자식 요소 사이 세로 간격2<div className="space-y-4">3 <div>첫 번째 항목</div>4 <div>두 번째 항목</div>5 <div>세 번째 항목</div>6</div>11. Effects — 그림자 & 불투명도
11.1. Box Shadow
1shadow-sm /* 작은 그림자 */2shadow /* 기본 그림자 */3shadow-md /* 중간 그림자 */4shadow-lg /* 큰 그림자 */5shadow-xl /* 더 큰 그림자 */6shadow-2xl /* 가장 큰 그림자 */7shadow-none /* 그림자 제거 */8
9/* 색상 그림자 */10shadow-lg shadow-black/5011.2. Opacity (불투명도)
1opacity-0 /* 완전 투명 */2opacity-50 /* 반투명 */3opacity-100 /* 불투명 */1// 1단계: shadow — 그림자 크기2<div className="shadow">기본 그림자</div>3<div className="shadow-md">중간 그림자</div>4<div className="shadow-xl">큰 그림자</div>1// 2단계: shadow-color — 색상 그림자2<div className="shadow-lg shadow-black/50">검은 그림자</div>3<div className="shadow-lg shadow-yellow-400/30">노란 그림자</div>1// 3단계: opacity — 요소 전체 투명도2<div className="opacity-100">완전 불투명</div>3<div className="opacity-50">반투명</div>4<div className="opacity-0">완전 투명 (공간은 차지)</div>12. Filters — 필터 (Blur · Backdrop)
1blur-none blur-sm blur blur-md blur-lg blur-xl2
3/* 배경 블러 (유리 효과) */4backdrop-blur-sm backdrop-blur-md backdrop-blur-lg1// 1단계: blur — 요소 자체를 흐리게2<img className="blur-none" src={img} alt="" />3<img className="blur-sm" src={img} alt="" />4<img className="blur-lg" src={img} alt="" />1// 2단계: backdrop-blur — 요소 뒤 배경을 흐리게2<div className="backdrop-blur-sm">약하게 흐린 배경</div>3<div className="backdrop-blur-md">중간 흐린 배경</div>4<div className="backdrop-blur-lg">많이 흐린 배경</div>1// 3단계: backdrop-blur + bg-*/투명도 — 유리 효과2<div className="backdrop-blur-md bg-white/10">유리처럼 반투명한 카드</div>13. Transitions & Animation — 트랜지션
1transition /* all 속성 */2transition-colors /* 색상만 */3transition-transform4transition-opacity5duration-150 /* 150ms */6duration-300 /* 300ms */7ease-in ease-out ease-in-out1// 1단계: transition — 변화를 부드럽게 (hover와 함께)2<div className="transition hover:opacity-50">호버 시 서서히 반투명</div>1// 2단계: duration — 애니메이션 시간2<div className="transition duration-150 hover:opacity-50">빠름 (150ms)</div>3<div className="transition duration-500 hover:opacity-50">느림 (500ms)</div>1// 3단계: transition-colors — 색상만 전환2<div className="transition-colors duration-200 hover:bg-yellow-400">3 호버 시 배경색만 전환4</div>1// 4단계: transition-transform — 크기·위치 전환2<div className="transition-transform duration-300 hover:scale-105">3 호버 시 크기만 전환4</div>1// 5단계: ease — 가속도 곡선2<div className="transition duration-300 ease-in hover:opacity-0">천천히 시작</div>3<div className="transition duration-300 ease-out hover:opacity-0">천천히 끝</div>4<div className="transition duration-300 ease-in-out hover:opacity-0">양쪽 천천히</div>14. Transforms — 변형
1scale-95 scale-100 scale-105 scale-1102-translate-y-1 translate-x-23rotate-45 rotate-90 rotate-1801// 1단계: scale — 크기 변형2<div className="scale-75">75% 축소</div>3<div className="scale-100">기본 크기</div>4<div className="scale-110">110% 확대</div>1// 2단계: translate — 위치 이동 (공간은 유지)2<div className="translate-x-4">오른쪽으로 16px</div>3<div className="-translate-y-2">위로 8px</div>1// 3단계: rotate — 회전2<div className="rotate-45">45도 회전</div>3<div className="rotate-90">90도 회전</div>4<div className="rotate-180">180도 회전</div>1// 4단계: transition + transform — 부드러운 변형2<div className="transition-transform duration-300 hover:scale-110">3 호버 시 서서히 확대4</div>5<div className="transition-transform duration-300 hover:-translate-y-1">6 호버 시 서서히 위로 이동7</div>15. Interactivity — 상호작용 (State Variants · Cursor)
15.1. Cursor
1cursor-pointer cursor-default cursor-not-allowed cursor-wait15.2. 주요 State Variants
클래스 앞에 상태:를 붙이면 해당 상태일 때만 적용된다.
| Variant | 설명 | 예시 |
|---|---|---|
hover: | 마우스 올림 | hover:bg-yellow-400 |
focus: | 포커스 | focus:ring-2 |
active: | 클릭 중 | active:scale-95 |
disabled: | 비활성화 | disabled:opacity-50 |
checked: | 체크됨 | checked:bg-blue-600 |
group-hover: | 부모 hover 시 | group-hover:opacity-100 |
peer-focus: | 형제 포커스 시 | peer-focus:text-blue-500 |
first: | 첫 번째 자식 | first:mt-0 |
last: | 마지막 자식 | last:mb-0 |
odd: / even: | 홀수/짝수 | odd:bg-gray-50 |
1// 1단계: hover: — 마우스를 올렸을 때2<div className="hover:opacity-50">호버 시 반투명</div>3<div className="hover:bg-yellow-400">호버 시 노란 배경</div>1// 2단계: focus: — 포커스 받았을 때 (입력 필드 등)2<input className="focus:outline-none" />3<input className="focus:ring-2 focus:ring-yellow-400" />1// 3단계: active: — 클릭하는 순간2<button className="active:scale-95">클릭 시 줄어듦</button>3<button className="active:opacity-70">클릭 시 반투명</button>1// 4단계: disabled: — 비활성화 상태2<button disabled className="disabled:opacity-50">비활성 (흐리게)</button>3<button disabled className="disabled:cursor-not-allowed">비활성 (커서 금지)</button>1// 5단계: group-hover: — 부모에 hover 시 자식에 적용2<div className="group">3 <p className="group-hover:text-yellow-400">부모에 호버하면 색상 변경</p>4</div>5
6// 부모 hover 시 숨겨진 오버레이 표시7<div className="group relative">8 <img src={poster} />9 <div className="absolute inset-0 opacity-0 group-hover:opacity-100">10 오버레이11 </div>12</div>1// 6단계: odd: / even: — 홀짝 번째 스타일2<ul>3 <li className="odd:bg-gray-900 even:bg-gray-800">항목 1 (홀수 → 어두운)</li>4 <li className="odd:bg-gray-900 even:bg-gray-800">항목 2 (짝수 → 밝은)</li>5 <li className="odd:bg-gray-900 even:bg-gray-800">항목 3 (홀수 → 어두운)</li>6</ul>16. 반응형 (Breakpoint)
Tailwind는 모바일 퍼스트이다. 기본값이 모바일이고, 접두사로 더 큰 화면을 지정한다.
16.1. 기본 브레이크포인트
| 접두사 | 최소 너비 | 기기 |
|---|---|---|
| (없음) | 0px~ | 모바일 (기본) |
sm: | 640px~ | 소형 태블릿 |
md: | 768px~ | 태블릿 |
lg: | 1024px~ | 노트북 |
xl: | 1280px~ | 데스크탑 |
2xl: | 1536px~ | 대형 모니터 |
1// 1단계: 브레이크포인트 하나 — md 이상에서 적용2<p className="text-sm md:text-xl">md 이상에서 커짐</p>1// 2단계: 브레이크포인트 두 개 — 단계적으로 변경2<p className="text-sm md:text-lg lg:text-2xl">화면이 커질수록 텍스트도 커짐</p>1// 3단계: hidden / block 조합 — 특정 화면에서 보이기/숨기기2<div className="hidden md:block">md 이상에서만 보임</div>3<div className="block md:hidden">md 미만에서만 보임 (모바일 전용)</div>1// 4단계: flex-col → flex-row — 모바일: 세로, 데스크탑: 가로2<div className="flex flex-col md:flex-row">3 <div>첫 번째</div>4 <div>두 번째</div>5</div>1// 5단계: grid-cols 반응형 — 화면 크기에 따라 열 수 변경2<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">3 <div>카드 1</div>4 <div>카드 2</div>5 <div>카드 3</div>6 <div>카드 4</div>7</div>17. Dark Mode
17.1. 설정 (media 모드 — OS 자동)
1// OS 다크모드 설정에 따라 자동 전환2<div className="bg-white dark:bg-gray-900">3 라이트: 흰 배경 / 다크: 어두운 배경4</div>17.2. 수동 토글 방식 (class 모드)
1@import "tailwindcss";2
3@custom-variant dark (&:where(.dark, .dark *));1// HTML 루트에 dark 클래스 추가/제거로 제어2document.documentElement.classList.toggle('dark')1// 1단계: dark: 텍스트 색상2<p className="text-black dark:text-white">라이트: 검은색 / 다크: 흰색</p>3<p className="text-gray-700 dark:text-gray-300">라이트: 진한 회색 / 다크: 밝은 회색</p>1// 2단계: dark: 배경 색상2<div className="bg-white dark:bg-gray-900">라이트: 흰 배경 / 다크: 어두운 배경</div>3<div className="bg-gray-100 dark:bg-gray-800">라이트: 밝은 회색 / 다크: 짙은 회색</div>1// 3단계: 텍스트 + 배경 조합2<div className="bg-white dark:bg-gray-900 text-black dark:text-white">3 다크모드 대응 카드4</div>1// 4단계: 토글 버튼으로 직접 제어2function DarkToggle() {3 const [dark, setDark] = useState(false)4
5 const toggle = () => {6 setDark(prev => !prev)7 document.documentElement.classList.toggle('dark')8 }9
10 return (11 <button onClick={toggle}>12 {dark ? '🌙 다크' : '☀️ 라이트'}13 </button>14 )15}18.1. Header 분석
1<header className="fixed top-0 left-0 w-full py-4 px-2 bg-black/90 z-50">2 {/* fixed: 스크롤해도 고정 */}3 {/* top-0 left-0: 화면 최상단 좌측 */}4 {/* w-full: 전체 너비 */}5 {/* py-4 px-2: 상하 16px, 좌우 8px 패딩 */}6 {/* bg-black/90: 검은색 배경 90% 불투명 */}7 {/* z-50: 다른 요소 위에 표시 */}8 <div className="container mx-auto">9 <Link to="/">10 <h1 className="text-3xl text-yellow-300 font-bold">11 {/* text-3xl: 30px 텍스트 */}12 {/* text-yellow-300: 연한 노란색 */}13 {/* font-bold: 굵은 글씨 */}14 GOFLIX15 </h1>16 </Link>17 </div>18</header>18.2. 영화 카드 컴포넌트 패턴
1function MovieCard({ movie }) {2 return (3 <div className="group relative rounded-lg overflow-hidden cursor-pointer4 transition-transform duration-300 hover:scale-1055 shadow-lg hover:shadow-yellow-400/30">6 {/* 포스터 이미지 */}7 <img8 src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}9 alt={movie.title}10 className="w-full aspect-[2/3] object-cover"11 />12 {/* 호버 오버레이 */}13 <div className="absolute inset-0 bg-black/70 opacity-0 group-hover:opacity-10014 transition-opacity duration-300 flex flex-col justify-end p-4">15 <h3 className="text-white font-bold text-sm line-clamp-2">{movie.title}</h3>16 <p className="text-yellow-300 text-xs mt-1">⭐ {movie.vote_average.toFixed(1)}</p>17 </div>18 </div>19 );20}18.3. 전체 페이지 레이아웃
1// App.jsx2<main className="bg-black text-white min-h-screen pt-16">3 {/* bg-black: 검은 배경 */}4 {/* text-white: 기본 텍스트 흰색 */}5 {/* min-h-screen: 최소 전체 높이 */}6 {/* pt-16: 상단 64px (fixed 헤더 높이만큼) */}7 <Outlet />8</main>9
10// 홈 페이지11<section className="container mx-auto px-4 py-8">12 <h2 className="text-2xl font-bold mb-6 text-yellow-300">인기 영화</h2>13 <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4">14 {movies.map(movie => <MovieCard key={movie.id} movie={movie} />)}15 </div>16</section>18.4. 버튼 스타일 패턴
1{/* 주요 액션 버튼 */}2<button className="bg-yellow-400 text-black font-bold px-6 py-2 rounded-lg3 hover:bg-yellow-300 active:scale-954 transition-all duration-200 cursor-pointer">5 자세히 보기6</button>7
8{/* 보조 버튼 (아웃라인) */}9<button className="border-2 border-white text-white font-semibold px-6 py-2 rounded-lg10 hover:bg-white hover:text-black11 transition-all duration-200 cursor-pointer">12 목록 추가13</button>18.5. 영화 상세 페이지
1function MovieDetail({ movie }) {2 return (3 <div className="relative min-h-screen bg-black text-white">4 {/* 배경 이미지 */}5 <div className="relative h-[60vh]">6 <img7 src={`https://image.tmdb.org/t/p/original${movie.backdrop_path}`}8 className="w-full h-full object-cover"9 />10 <div className="absolute inset-0 bg-gradient-to-t from-black via-black/40 to-transparent" />11 </div>12
13 {/* 콘텐츠 */}14 <div className="container mx-auto px-4 -mt-32 relative z-10">15 <div className="flex flex-col md:flex-row gap-8">16 <img17 src={`https://image.tmdb.org/t/p/w300${movie.poster_path}`}18 className="w-40 md:w-56 rounded-xl shadow-2xl flex-none mx-auto md:mx-0"19 />20 <div className="flex-1">21 <h1 className="text-3xl md:text-5xl font-black">{movie.title}</h1>22 <div className="flex items-center gap-3 mt-3 text-sm text-gray-400">23 <span className="text-yellow-400 font-bold">⭐ {movie.vote_average.toFixed(1)}</span>24 <span>{movie.release_date.slice(0, 4)}</span>25 </div>26 <p className="mt-4 text-gray-300 leading-relaxed max-w-2xl line-clamp-4 md:line-clamp-none">27 {movie.overview}28 </p>29 <div className="flex gap-3 mt-6">30 <button className="bg-yellow-400 text-black font-bold px-6 py-3 rounded-lg31 hover:bg-yellow-300 active:scale-95 transition-all duration-200">32 ▶ 재생33 </button>34 <button className="border border-white/40 text-white px-6 py-3 rounded-lg35 hover:bg-white/10 transition-all duration-200">36 + 내 목록37 </button>38 </div>39 </div>40 </div>41 </div>42 </div>43 )44}요약
클래스 조합 팁
복잡한 컴포넌트는 관심사별로 줄을 나눠 읽기 좋게 작성한다.
레이아웃 → 크기 → 색상 → 상태 순으로 배치하면 유지보수가 편하다.
주의
자주 하는 실수
hover:scale-105만 쓰면 애니메이션이 없음 →transition-transform duration-300필수opacity-0 group-hover:opacity-100을 쓸 때 부모에group클래스 빠뜨리지 않기fixed헤더가 있으면 main에pt-{헤더높이}필수 (겹침 방지)