- 发布于
Tailwind CSS 实用指南:原子化 CSS 框架的最佳实践
- 作者

- 姓名
- 全能波
- GitHub
- @weicracker
Tailwind CSS 实用指南:原子化 CSS 框架的最佳实践
Tailwind CSS 是一个功能优先的 CSS 框架,它提供了大量的原子化 CSS 类,让开发者能够快速构建现代化的用户界面。本文将深入探讨 Tailwind CSS 的核心概念和实践应用。
Tailwind CSS 核心理念
实用优先的设计哲学
<!-- 传统 CSS 方式 -->
<style>
.card {
background-color: white;
border-radius: 0.5rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
padding: 1.5rem;
margin-bottom: 1rem;
}
.card-title {
font-size: 1.25rem;
font-weight: 600;
color: #1f2937;
margin-bottom: 0.5rem;
}
.card-content {
color: #6b7280;
line-height: 1.5;
}
</style>
<div class="card">
<h3 class="card-title">卡片标题</h3>
<p class="card-content">这是卡片的内容描述。</p>
</div>
<!-- Tailwind CSS 方式 -->
<div class="mb-4 rounded-lg bg-white p-6 shadow-md">
<h3 class="mb-2 text-xl font-semibold text-gray-800">卡片标题</h3>
<p class="leading-relaxed text-gray-600">这是卡片的内容描述。</p>
</div>
响应式设计
<!-- 响应式布局 -->
<div class="container mx-auto px-4">
<!-- 移动端单列,平板双列,桌面三列 -->
<div class="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
<div class="rounded-lg bg-white p-6 shadow-md">
<h3 class="mb-4 text-lg font-semibold">产品卡片</h3>
<img src="product.jpg" alt="产品图片" class="mb-4 h-48 w-full rounded-md object-cover" />
<p class="mb-4 text-sm text-gray-600">产品描述信息</p>
<button
class="w-full rounded-md bg-blue-600 px-4 py-2 font-medium text-white transition-colors duration-200 hover:bg-blue-700"
>
立即购买
</button>
</div>
</div>
</div>
<!-- 响应式文字大小 -->
<h1 class="text-center text-2xl font-bold sm:text-3xl md:text-4xl lg:text-5xl xl:text-6xl">
响应式标题
</h1>
<!-- 响应式间距 -->
<div class="p-4 sm:p-6 md:p-8 lg:p-12">
<div class="space-y-4 sm:space-y-6 md:space-y-8">
<p>段落内容</p>
<p>段落内容</p>
</div>
</div>
<!-- 响应式显示/隐藏 -->
<div class="block md:hidden">
<!-- 移动端显示的内容 -->
<button class="w-full rounded-lg bg-blue-600 py-3 text-white">移动端菜单</button>
</div>
<div class="hidden space-x-6 md:flex">
<!-- 桌面端显示的导航 -->
<a href="#" class="text-gray-700 hover:text-blue-600">首页</a>
<a href="#" class="text-gray-700 hover:text-blue-600">产品</a>
<a href="#" class="text-gray-700 hover:text-blue-600">关于</a>
</div>
布局系统
Flexbox 布局
<!-- 基础 Flex 布局 -->
<div class="flex items-center justify-between bg-gray-100 p-4">
<div class="flex items-center space-x-3">
<img src="avatar.jpg" alt="头像" class="h-10 w-10 rounded-full" />
<div>
<h4 class="font-medium text-gray-900">用户名</h4>
<p class="text-sm text-gray-500">用户描述</p>
</div>
</div>
<button class="rounded-md bg-blue-600 px-4 py-2 text-white hover:bg-blue-700">关注</button>
</div>
<!-- 垂直居中布局 -->
<div class="flex min-h-screen items-center justify-center bg-gray-50">
<div class="w-full max-w-md rounded-lg bg-white p-8 shadow-md">
<h2 class="mb-8 text-center text-2xl font-bold text-gray-900">登录</h2>
<form class="space-y-6">
<div>
<label class="mb-2 block text-sm font-medium text-gray-700"> 邮箱地址 </label>
<input
type="email"
class="w-full rounded-md border border-gray-300 px-3 py-2 focus:border-transparent focus:ring-2 focus:ring-blue-500 focus:outline-none"
/>
</div>
<div>
<label class="mb-2 block text-sm font-medium text-gray-700"> 密码 </label>
<input
type="password"
class="w-full rounded-md border border-gray-300 px-3 py-2 focus:border-transparent focus:ring-2 focus:ring-blue-500 focus:outline-none"
/>
</div>
<button
type="submit"
class="w-full rounded-md bg-blue-600 px-4 py-2 text-white transition-colors duration-200 hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:outline-none"
>
登录
</button>
</form>
</div>
</div>
<!-- 复杂 Flex 布局 -->
<div class="flex min-h-screen flex-col lg:flex-row">
<!-- 侧边栏 -->
<div class="w-full bg-gray-800 text-white lg:w-64">
<div class="p-4">
<h1 class="text-xl font-bold">管理后台</h1>
</div>
<nav class="mt-8">
<a
href="#"
class="flex items-center px-4 py-2 text-gray-300 hover:bg-gray-700 hover:text-white"
>
<svg class="mr-3 h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
<path
d="M3 4a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H4a1 1 0 01-1-1V4zM3 10a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H4a1 1 0 01-1-1v-6zM14 9a1 1 0 00-1 1v6a1 1 0 001 1h2a1 1 0 001-1v-6a1 1 0 00-1-1h-2z"
></path>
</svg>
仪表板
</a>
</nav>
</div>
<!-- 主内容区 -->
<div class="flex flex-1 flex-col overflow-hidden">
<!-- 顶部导航 -->
<header class="border-b border-gray-200 bg-white shadow-sm">
<div class="flex items-center justify-between px-6 py-4">
<h2 class="text-xl font-semibold text-gray-800">页面标题</h2>
<div class="flex items-center space-x-4">
<button class="text-gray-500 hover:text-gray-700">
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 17h5l-5 5-5-5h5v-12"
></path>
</svg>
</button>
</div>
</div>
</header>
<!-- 内容区域 -->
<main class="flex-1 overflow-y-auto bg-gray-50 p-6">
<div class="mx-auto max-w-7xl">
<!-- 页面内容 -->
</div>
</main>
</div>
</div>
Grid 布局
<!-- 基础 Grid 布局 -->
<div class="grid grid-cols-1 gap-6 p-6 sm:grid-cols-2 lg:grid-cols-4">
<div class="rounded-lg bg-white p-6 shadow-md">
<h3 class="mb-2 text-lg font-semibold">统计卡片 1</h3>
<p class="text-3xl font-bold text-blue-600">1,234</p>
<p class="text-sm text-gray-500">总用户数</p>
</div>
<div class="rounded-lg bg-white p-6 shadow-md">
<h3 class="mb-2 text-lg font-semibold">统计卡片 2</h3>
<p class="text-3xl font-bold text-green-600">5,678</p>
<p class="text-sm text-gray-500">总订单数</p>
</div>
<div class="rounded-lg bg-white p-6 shadow-md">
<h3 class="mb-2 text-lg font-semibold">统计卡片 3</h3>
<p class="text-3xl font-bold text-yellow-600">$12,345</p>
<p class="text-sm text-gray-500">总收入</p>
</div>
<div class="rounded-lg bg-white p-6 shadow-md">
<h3 class="mb-2 text-lg font-semibold">统计卡片 4</h3>
<p class="text-3xl font-bold text-red-600">89%</p>
<p class="text-sm text-gray-500">转化率</p>
</div>
</div>
<!-- 复杂 Grid 布局 -->
<div class="grid grid-cols-12 gap-6 p-6">
<!-- 主要内容区域 -->
<div class="col-span-12 lg:col-span-8">
<div class="rounded-lg bg-white p-6 shadow-md">
<h2 class="mb-4 text-xl font-bold">主要内容</h2>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
<div class="rounded-lg bg-gray-50 p-4">
<h3 class="mb-2 font-semibold">子内容 1</h3>
<p class="text-gray-600">内容描述</p>
</div>
<div class="rounded-lg bg-gray-50 p-4">
<h3 class="mb-2 font-semibold">子内容 2</h3>
<p class="text-gray-600">内容描述</p>
</div>
</div>
</div>
</div>
<!-- 侧边栏 -->
<div class="col-span-12 lg:col-span-4">
<div class="rounded-lg bg-white p-6 shadow-md">
<h3 class="mb-4 text-lg font-semibold">侧边栏</h3>
<div class="space-y-4">
<div class="border-l-4 border-blue-500 pl-4">
<h4 class="font-medium">重要通知</h4>
<p class="text-sm text-gray-600">通知内容</p>
</div>
<div class="border-l-4 border-green-500 pl-4">
<h4 class="font-medium">系统更新</h4>
<p class="text-sm text-gray-600">更新内容</p>
</div>
</div>
</div>
</div>
</div>
<!-- 瀑布流布局 -->
<div class="columns-1 gap-6 p-6 sm:columns-2 lg:columns-3 xl:columns-4">
<div class="mb-6 break-inside-avoid overflow-hidden rounded-lg bg-white shadow-md">
<img src="image1.jpg" alt="图片" class="h-auto w-full" />
<div class="p-4">
<h3 class="mb-2 font-semibold">图片标题</h3>
<p class="text-sm text-gray-600">图片描述</p>
</div>
</div>
<div class="mb-6 break-inside-avoid rounded-lg bg-white p-4 shadow-md">
<h3 class="mb-2 font-semibold">文本卡片</h3>
<p class="text-gray-600">这是一个纯文本的卡片内容,高度会根据内容自动调整。</p>
</div>
</div>
组件设计模式
按钮组件
<!-- 基础按钮样式 -->
<div class="space-y-4 space-x-4">
<!-- 主要按钮 -->
<button
class="rounded-md bg-blue-600 px-4 py-2 font-medium text-white transition-colors duration-200 hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:outline-none"
>
主要按钮
</button>
<!-- 次要按钮 -->
<button
class="rounded-md bg-gray-200 px-4 py-2 font-medium text-gray-800 transition-colors duration-200 hover:bg-gray-300 focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 focus:outline-none"
>
次要按钮
</button>
<!-- 危险按钮 -->
<button
class="rounded-md bg-red-600 px-4 py-2 font-medium text-white transition-colors duration-200 hover:bg-red-700 focus:ring-2 focus:ring-red-500 focus:ring-offset-2 focus:outline-none"
>
危险按钮
</button>
<!-- 轮廓按钮 -->
<button
class="rounded-md border-2 border-blue-600 px-4 py-2 font-medium text-blue-600 transition-all duration-200 hover:bg-blue-600 hover:text-white focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:outline-none"
>
轮廓按钮
</button>
<!-- 文本按钮 -->
<button
class="rounded-md px-4 py-2 font-medium text-blue-600 transition-all duration-200 hover:bg-blue-50 hover:text-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:outline-none"
>
文本按钮
</button>
</div>
<!-- 按钮尺寸 -->
<div class="space-x-4">
<!-- 小按钮 -->
<button class="rounded-md bg-blue-600 px-3 py-1 text-sm font-medium text-white hover:bg-blue-700">
小按钮
</button>
<!-- 中等按钮 -->
<button class="rounded-md bg-blue-600 px-4 py-2 font-medium text-white hover:bg-blue-700">
中等按钮
</button>
<!-- 大按钮 -->
<button class="rounded-md bg-blue-600 px-6 py-3 text-lg font-medium text-white hover:bg-blue-700">
大按钮
</button>
</div>
<!-- 带图标的按钮 -->
<div class="space-x-4">
<button
class="inline-flex items-center rounded-md bg-blue-600 px-4 py-2 font-medium text-white transition-colors duration-200 hover:bg-blue-700"
>
<svg class="mr-2 h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 6v6m0 0v6m0-6h6m-6 0H6"
></path>
</svg>
添加项目
</button>
<button
class="inline-flex items-center rounded-md bg-green-600 px-4 py-2 font-medium text-white transition-colors duration-200 hover:bg-green-700"
>
<svg class="mr-2 h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
></path>
</svg>
下载文件
</button>
</div>
<!-- 加载状态按钮 -->
<button
class="inline-flex cursor-not-allowed items-center rounded-md bg-blue-600 px-4 py-2 font-medium text-white opacity-75"
disabled
>
<svg
class="mr-3 -ml-1 h-5 w-5 animate-spin text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
class="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
stroke-width="4"
></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
处理中...
</button>
表单组件
<!-- 完整表单示例 -->
<form class="mx-auto max-w-lg rounded-lg bg-white p-8 shadow-md">
<h2 class="mb-6 text-2xl font-bold text-gray-900">用户注册</h2>
<!-- 文本输入框 -->
<div class="mb-6">
<label for="username" class="mb-2 block text-sm font-medium text-gray-700">
用户名 <span class="text-red-500">*</span>
</label>
<input
type="text"
id="username"
name="username"
class="w-full rounded-md border border-gray-300 px-3 py-2 placeholder-gray-400 shadow-sm focus:border-transparent focus:ring-2 focus:ring-blue-500 focus:outline-none"
placeholder="请输入用户名"
required
/>
<p class="mt-1 text-sm text-gray-500">用户名必须是3-20个字符</p>
</div>
<!-- 邮箱输入框 -->
<div class="mb-6">
<label for="email" class="mb-2 block text-sm font-medium text-gray-700">
邮箱地址 <span class="text-red-500">*</span>
</label>
<div class="relative">
<input
type="email"
id="email"
name="email"
class="w-full rounded-md border border-gray-300 py-2 pr-3 pl-10 shadow-sm focus:border-transparent focus:ring-2 focus:ring-blue-500 focus:outline-none"
placeholder="请输入邮箱地址"
required
/>
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M16 12a4 4 0 10-8 0 4 4 0 008 0zm0 0v1.5a2.5 2.5 0 005 0V12a9 9 0 10-9 9m4.5-1.206a8.959 8.959 0 01-4.5 1.207"
></path>
</svg>
</div>
</div>
</div>
<!-- 密码输入框 -->
<div class="mb-6">
<label for="password" class="mb-2 block text-sm font-medium text-gray-700">
密码 <span class="text-red-500">*</span>
</label>
<input
type="password"
id="password"
name="password"
class="w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-transparent focus:ring-2 focus:ring-blue-500 focus:outline-none"
placeholder="请输入密码"
required
/>
</div>
<!-- 选择框 -->
<div class="mb-6">
<label for="role" class="mb-2 block text-sm font-medium text-gray-700"> 用户角色 </label>
<select
id="role"
name="role"
class="w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-transparent focus:ring-2 focus:ring-blue-500 focus:outline-none"
>
<option value="">请选择角色</option>
<option value="user">普通用户</option>
<option value="admin">管理员</option>
<option value="moderator">版主</option>
</select>
</div>
<!-- 复选框 -->
<div class="mb-6">
<div class="flex items-center">
<input
id="terms"
name="terms"
type="checkbox"
class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
/>
<label for="terms" class="ml-2 block text-sm text-gray-700">
我同意 <a href="#" class="text-blue-600 hover:text-blue-500">服务条款</a> 和
<a href="#" class="text-blue-600 hover:text-blue-500">隐私政策</a>
</label>
</div>
</div>
<!-- 单选框组 -->
<div class="mb-6">
<fieldset>
<legend class="mb-2 block text-sm font-medium text-gray-700">通知偏好</legend>
<div class="space-y-2">
<div class="flex items-center">
<input
id="email-notifications"
name="notifications"
type="radio"
value="email"
class="h-4 w-4 border-gray-300 text-blue-600 focus:ring-blue-500"
/>
<label for="email-notifications" class="ml-2 block text-sm text-gray-700">
邮件通知
</label>
</div>
<div class="flex items-center">
<input
id="sms-notifications"
name="notifications"
type="radio"
value="sms"
class="h-4 w-4 border-gray-300 text-blue-600 focus:ring-blue-500"
/>
<label for="sms-notifications" class="ml-2 block text-sm text-gray-700"> 短信通知 </label>
</div>
<div class="flex items-center">
<input
id="no-notifications"
name="notifications"
type="radio"
value="none"
class="h-4 w-4 border-gray-300 text-blue-600 focus:ring-blue-500"
/>
<label for="no-notifications" class="ml-2 block text-sm text-gray-700">
不接收通知
</label>
</div>
</div>
</fieldset>
</div>
<!-- 文本域 -->
<div class="mb-6">
<label for="bio" class="mb-2 block text-sm font-medium text-gray-700"> 个人简介 </label>
<textarea
id="bio"
name="bio"
rows="4"
class="w-full resize-none rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-transparent focus:ring-2 focus:ring-blue-500 focus:outline-none"
placeholder="请简单介绍一下自己..."
></textarea>
</div>
<!-- 提交按钮 -->
<div class="flex items-center justify-between">
<button
type="button"
class="rounded-md px-4 py-2 font-medium text-gray-600 transition-colors duration-200 hover:text-gray-800"
>
取消
</button>
<button
type="submit"
class="rounded-md bg-blue-600 px-6 py-2 font-medium text-white transition-colors duration-200 hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:outline-none"
>
注册账户
</button>
</div>
</form>
卡片组件
<!-- 基础卡片 -->
<div class="overflow-hidden rounded-lg bg-white shadow-md">
<img src="product.jpg" alt="产品图片" class="h-48 w-full object-cover" />
<div class="p-6">
<h3 class="mb-2 text-xl font-semibold text-gray-900">产品标题</h3>
<p class="mb-4 text-gray-600">产品描述信息,介绍产品的主要特点和优势。</p>
<div class="flex items-center justify-between">
<span class="text-2xl font-bold text-blue-600">¥299</span>
<button
class="rounded-md bg-blue-600 px-4 py-2 font-medium text-white transition-colors duration-200 hover:bg-blue-700"
>
立即购买
</button>
</div>
</div>
</div>
<!-- 用户卡片 -->
<div class="rounded-lg bg-white p-6 shadow-md">
<div class="flex items-center space-x-4">
<img src="avatar.jpg" alt="用户头像" class="h-16 w-16 rounded-full" />
<div class="flex-1">
<h3 class="text-lg font-semibold text-gray-900">张三</h3>
<p class="text-gray-600">前端开发工程师</p>
<div class="mt-2 flex items-center space-x-4">
<span class="text-sm text-gray-500">关注者: 1,234</span>
<span class="text-sm text-gray-500">文章: 56</span>
</div>
</div>
<button
class="rounded-md bg-blue-600 px-4 py-2 font-medium text-white transition-colors duration-200 hover:bg-blue-700"
>
关注
</button>
</div>
</div>
<!-- 统计卡片 -->
<div class="rounded-lg bg-gradient-to-r from-blue-500 to-blue-600 p-6 text-white shadow-md">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-blue-100">总用户数</p>
<p class="text-3xl font-bold">12,345</p>
<p class="text-sm text-blue-100"><span class="text-green-300">↗ 12%</span> 比上月增长</p>
</div>
<div class="bg-opacity-30 rounded-full bg-blue-400 p-3">
<svg class="h-8 w-8" fill="currentColor" viewBox="0 0 20 20">
<path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
</div>
</div>
自定义配置
tailwind.config.js 配置
// tailwind.config.js
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
'./app/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
// 自定义颜色
colors: {
primary: {
50: '#eff6ff',
100: '#dbeafe',
200: '#bfdbfe',
300: '#93c5fd',
400: '#60a5fa',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
},
secondary: {
50: '#f0fdf4',
100: '#dcfce7',
200: '#bbf7d0',
300: '#86efac',
400: '#4ade80',
500: '#22c55e',
600: '#16a34a',
700: '#15803d',
800: '#166534',
900: '#14532d',
},
},
// 自定义字体
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
serif: ['Georgia', 'serif'],
mono: ['Fira Code', 'monospace'],
},
// 自定义间距
spacing: {
18: '4.5rem',
88: '22rem',
128: '32rem',
},
// 自定义断点
screens: {
xs: '475px',
'3xl': '1600px',
},
// 自定义动画
animation: {
'fade-in': 'fadeIn 0.5s ease-in-out',
'slide-up': 'slideUp 0.3s ease-out',
'bounce-slow': 'bounce 2s infinite',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
slideUp: {
'0%': { transform: 'translateY(100%)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
},
},
// 自定义阴影
boxShadow: {
soft: '0 2px 15px -3px rgba(0, 0, 0, 0.07), 0 10px 20px -2px rgba(0, 0, 0, 0.04)',
strong: '0 10px 25px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
},
// 自定义边框圆角
borderRadius: {
xl: '1rem',
'2xl': '1.5rem',
'3xl': '2rem',
},
},
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
require('@tailwindcss/aspect-ratio'),
// 自定义插件
function ({ addUtilities, addComponents, theme }) {
// 添加自定义工具类
addUtilities({
'.text-shadow': {
textShadow: '2px 2px 4px rgba(0, 0, 0, 0.1)',
},
'.text-shadow-lg': {
textShadow: '4px 4px 8px rgba(0, 0, 0, 0.2)',
},
})
// 添加自定义组件
addComponents({
'.btn': {
padding: theme('spacing.2') + ' ' + theme('spacing.4'),
borderRadius: theme('borderRadius.md'),
fontWeight: theme('fontWeight.medium'),
transition: 'all 0.2s ease-in-out',
'&:focus': {
outline: 'none',
boxShadow: '0 0 0 3px rgba(59, 130, 246, 0.5)',
},
},
'.btn-primary': {
backgroundColor: theme('colors.blue.600'),
color: theme('colors.white'),
'&:hover': {
backgroundColor: theme('colors.blue.700'),
},
},
})
},
],
}
最佳实践
1. 组件抽象
// React 组件示例
import React from 'react'
import clsx from 'clsx'
// 按钮组件
const Button = ({
children,
variant = 'primary',
size = 'md',
disabled = false,
className = '',
...props
}) => {
const baseClasses =
'inline-flex items-center justify-center font-medium rounded-md transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2'
const variantClasses = {
primary: 'bg-blue-600 hover:bg-blue-700 text-white focus:ring-blue-500',
secondary: 'bg-gray-200 hover:bg-gray-300 text-gray-800 focus:ring-gray-500',
danger: 'bg-red-600 hover:bg-red-700 text-white focus:ring-red-500',
outline:
'border-2 border-blue-600 text-blue-600 hover:bg-blue-600 hover:text-white focus:ring-blue-500',
}
const sizeClasses = {
sm: 'px-3 py-1 text-sm',
md: 'px-4 py-2',
lg: 'px-6 py-3 text-lg',
}
const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : ''
return (
<button
className={clsx(
baseClasses,
variantClasses[variant],
sizeClasses[size],
disabledClasses,
className
)}
disabled={disabled}
{...props}
>
{children}
</button>
)
}
// 卡片组件
const Card = ({ children, className = '', ...props }) => {
return (
<div className={clsx('overflow-hidden rounded-lg bg-white shadow-md', className)} {...props}>
{children}
</div>
)
}
const CardHeader = ({ children, className = '' }) => (
<div className={clsx('border-b border-gray-200 px-6 py-4', className)}>{children}</div>
)
const CardBody = ({ children, className = '' }) => (
<div className={clsx('px-6 py-4', className)}>{children}</div>
)
const CardFooter = ({ children, className = '' }) => (
<div className={clsx('border-t border-gray-200 bg-gray-50 px-6 py-4', className)}>{children}</div>
)
// 使用示例
const ExampleCard = () => (
<Card className="max-w-md">
<CardHeader>
<h3 className="text-lg font-semibold">卡片标题</h3>
</CardHeader>
<CardBody>
<p className="text-gray-600">这是卡片的内容区域。</p>
</CardBody>
<CardFooter>
<div className="flex justify-end space-x-2">
<Button variant="secondary" size="sm">
取消
</Button>
<Button variant="primary" size="sm">
确认
</Button>
</div>
</CardFooter>
</Card>
)
2. 性能优化
// 生产环境优化配置
module.exports = {
content: ['./src/**/*.{js,jsx,ts,tsx}'],
theme: {
extend: {},
},
plugins: [],
// 生产环境移除未使用的样式
purge: {
enabled: process.env.NODE_ENV === 'production',
content: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
// 保护特定类名不被移除
safelist: ['bg-red-500', 'text-3xl', 'lg:text-4xl'],
},
}
总结
Tailwind CSS 为现代前端开发提供了高效的样式解决方案:
- 实用优先:原子化 CSS 类提高开发效率
- 响应式设计:内置的响应式修饰符
- 组件化:通过抽象创建可复用的组件
- 自定义配置:灵活的主题定制能力
- 性能优化:生产环境自动移除未使用的样式
掌握 Tailwind CSS,你就能快速构建出美观、响应式的现代用户界面!
Tailwind CSS 是现代前端开发的强大工具,值得深入学习和实践。