CSS를 작성하는 전통적인 방식은 HTML에 클래스명을 붙이고, 별도의 CSS 파일에 스타일을 정의합니다. 이 접근법은 두 파일을 오가며 작업해야 하고, 클래스명 충돌이나 사용하지 않는 스타일 누적 같은 문제를 낳습니다.
Tailwind CSS는 다른 방향을 선택합니다. flex, p-4, text-lg처럼 단일 CSS 속성에 대응하는 작은 클래스들을 HTML에 직접 조합합니다. 별도의 CSS 파일을 작성하지 않아도 되며, 빌드 시 실제로 사용된 클래스만 포함되므로 번들 크기가 작습니다.
npm install tailwindcss @tailwindcss/vite
Vite 기반 프로젝트의 경우 vite.config.ts에 플러그인을 추가합니다.
// vite.config.ts
import tailwindcss from "@tailwindcss/vite";
export default {
plugins: [tailwindcss()],
};
CSS 진입점 파일에 임포트를 추가합니다.
/* index.css */
@import "tailwindcss";
Tailwind의 각 클래스는 CSS 속성 하나를 담당합니다. 여러 클래스를 조합하여 원하는 스타일을 만듭니다.
<!-- 기존 방식 -->
<div class="card">내용</div>
<style>
.card {
display: flex;
padding: 16px;
background-color: white;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
</style>
<!-- Tailwind 방식 -->
<div class="flex p-4 bg-white rounded-lg shadow-sm">내용</div>
자주 사용하는 유틸리티 클래스 목록입니다.
| 클래스 | CSS 속성 |
|---|---|
flex | display: flex |
p-4 | padding: 1rem |
mt-2 | margin-top: 0.5rem |
text-lg | font-size: 1.125rem |
font-bold | font-weight: 700 |
text-gray-700 | color: #374151 |
bg-blue-500 | background-color: #3b82f6 |
rounded-md | border-radius: 0.375rem |
w-full | width: 100% |
hidden | display: none |
숫자 스케일은 대부분 0.25rem(4px) 단위입니다. p-1은 4px, p-2는 8px, p-4는 16px입니다.
Tailwind는 모바일 퍼스트 방식을 사용합니다. 접두사 없는 클래스가 기본(모바일) 스타일이고, sm:, md:, lg:, xl: 접두사를 붙이면 해당 브레이크포인트 이상에서 적용됩니다.
<!-- 모바일: 1열, 태블릿: 2열, 데스크탑: 3열 -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div>항목 1</div>
<div>항목 2</div>
<div>항목 3</div>
</div>
<!-- 모바일: 세로 정렬, 데스크탑: 가로 정렬 -->
<div class="flex flex-col lg:flex-row items-center gap-6">
<img class="w-full lg:w-48" src="..." />
<p class="text-sm lg:text-base">설명 텍스트</p>
</div>
Breakpoint: 반응형 스타일이 전환되는 기준 뷰포트 너비
Tailwind의 기본 브레이크포인트는 다음과 같습니다.
0px 640px 768px 1024px 1280px 1536px
| | | | | |
[ (default) ]
[ sm: ]
[ md: ]
[ lg: ]
[ xl: ]
[ 2xl: ]
tailwind.config.js에서 커스텀 브레이크포인트를 추가하거나 기본값을 덮어쓸 수 있습니다.
// tailwind.config.js
module.exports = {
theme: {
screens: {
tablet: "640px",
laptop: "1024px",
desktop: "1280px",
},
},
};
tailwind.config.js의 theme 섹션에서 프로젝트 디자인 시스템을 정의합니다. extend를 사용하면 기본값을 유지하면서 추가합니다.
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
brand: {
50: "#eff6ff",
500: "#3b82f6",
900: "#1e3a8a",
},
// 사용법: text-brand-500, bg-brand-50
},
fontFamily: {
sans: ["Pretendard", "sans-serif"],
mono: ["JetBrains Mono", "monospace"],
},
spacing: {
18: "4.5rem", // p-18, m-18 등으로 사용
22: "5.5rem",
},
borderRadius: {
"4xl": "2rem",
},
},
},
};
<button class="bg-brand-500 hover:bg-brand-900 font-sans px-18 rounded-4xl">
커스텀 테마 버튼
</button>
Variant는 CSS의 가상 클래스(pseudo-class)와 가상 요소(pseudo-element)를 클래스 형태로 표현합니다.
<!-- 인터랙션 상태 -->
<button class="bg-blue-500 hover:bg-blue-700 active:scale-95 transition-all">
버튼
</button>
<!-- 폼 상태 -->
<input class="border focus:outline-none focus:ring-2 focus:ring-blue-500
disabled:opacity-50 disabled:cursor-not-allowed" />
<!-- 그룹 상태 — 부모에 group, 자식에 group-hover: -->
<div class="group cursor-pointer">
<img class="group-hover:scale-105 transition-transform" src="..." />
<p class="text-gray-600 group-hover:text-blue-600">제목</p>
</div>
<!-- 가상 요소 -->
<p class="before:content-['★'] before:text-yellow-400 before:mr-1">
추천 항목
</p>
자주 사용하는 Variant 목록입니다.
| Variant | 적용 조건 |
|---|---|
hover: | 마우스 호버 |
focus: | 포커스 상태 |
active: | 클릭/탭 중 |
disabled: | disabled 속성 |
dark: | 다크 모드 |
first: | 첫 번째 자식 |
last: | 마지막 자식 |
odd: / even: | 홀수/짝수 자식 |
group-hover: | 부모 hover 시 |
peer-focus: | 형제 focus 시 |
Plugin: Tailwind의 기본 유틸리티를 확장하거나 새로운 클래스를 추가하는 확장 시스템
공식 플러그인과 커뮤니티 플러그인으로 기능을 확장합니다.
npm install @tailwindcss/typography @tailwindcss/forms
// tailwind.config.js
module.exports = {
plugins: [
require("@tailwindcss/typography"), // prose 클래스로 마크다운 스타일
require("@tailwindcss/forms"), // 폼 요소 기본 스타일 초기화
],
};
커스텀 플러그인을 직접 작성할 수도 있습니다.
const plugin = require("tailwindcss/plugin");
module.exports = {
plugins: [
plugin(function ({ addUtilities, addComponents, theme }) {
// 커스텀 유틸리티 추가
addUtilities({
".text-balance": { "text-wrap": "balance" },
".scrollbar-hide": {
"-ms-overflow-style": "none",
"scrollbar-width": "none",
},
});
// 커스텀 컴포넌트 추가
addComponents({
".btn-primary": {
backgroundColor: theme("colors.blue.500"),
color: "white",
padding: `${theme("spacing.2")} ${theme("spacing.4")}`,
borderRadius: theme("borderRadius.md"),
},
});
}),
],
};
tailwind.config.js는 Tailwind의 핵심 설정 파일입니다.
/** @type {import('tailwindcss').Config} */
module.exports = {
// 1. content: 클래스를 스캔할 파일 경로
// 여기 명시된 파일에서 사용된 클래스만 최종 CSS에 포함됨
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
// 2. theme: 디자인 토큰 정의
theme: {
extend: {
colors: { brand: "#0ea5e9" },
},
},
// 3. darkMode: 다크 모드 전략
darkMode: "class", // "media" 또는 "class"
// 4. plugins: 플러그인 목록
plugins: [
require("@tailwindcss/typography"),
],
};
content 설정이 잘못되면 빌드된 CSS에서 클래스가 누락됩니다. 동적으로 생성된 클래스명(템플릿 리터럴 등)은 스캔되지 않으므로 전체 클래스명을 문자열로 작성해야 합니다.
// 잘못된 방식 — 스캔 불가
const color = "blue";
<div className={`text-${color}-500`} />
// 올바른 방식 — 전체 클래스명 사용
const classMap = { blue: "text-blue-500", red: "text-red-500" };
<div className={classMap[color]} />
Tailwind는 media와 class 두 가지 다크 모드 전략을 제공합니다.
media 전략: 운영체제의 색상 모드 설정을 따릅니다.
// tailwind.config.js
darkMode: "media",
class 전략: html 또는 루트 요소에 dark 클래스가 있을 때 적용됩니다. JavaScript로 토글할 수 있어 더 유연합니다.
darkMode: "class",
// 다크 모드 토글 구현
function ThemeToggle() {
const toggleDark = () => {
document.documentElement.classList.toggle("dark");
};
return <button onClick={toggleDark}>테마 전환</button>;
}
// dark: 접두사로 다크 모드 스타일 적용
<div class="bg-white text-gray-900 dark:bg-gray-900 dark:text-gray-100">
<h1 class="text-2xl font-bold text-blue-600 dark:text-blue-400">제목</h1>
<p class="text-gray-600 dark:text-gray-300">본문 내용</p>
<button class="bg-blue-500 dark:bg-blue-700 text-white px-4 py-2 rounded">
버튼
</button>
</div>
CSS 변수와 조합하면 테마를 더 체계적으로 관리할 수 있습니다.
/* index.css */
:root {
--color-bg: 255 255 255;
--color-text: 17 24 39;
}
.dark {
--color-bg: 17 24 39;
--color-text: 243 244 246;
}
// tailwind.config.js
colors: {
bg: "rgb(var(--color-bg) / <alpha-value>)",
text: "rgb(var(--color-text) / <alpha-value>)",
}
Tailwind CSS는 CSS 작성 방식을 바꿉니다. 클래스명을 고민하지 않아도 되고, 스타일 파일과 마크업 파일을 오갈 필요가 없습니다. 팀 전체가 동일한 디자인 토큰을 공유하므로 일관성 있는 UI를 유지하기 쉽습니다.
처음에는 클래스가 길어 낯설게 느껴질 수 있습니다. 그러나 요소의 스타일을 파악하기 위해 CSS 파일을 찾아다닐 필요가 없다는 점에서 가독성이 오히려 높아집니다.