发布于

Tailwind CSS 实用指南:原子化 CSS 框架的最佳实践

作者

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 为现代前端开发提供了高效的样式解决方案:

  1. 实用优先:原子化 CSS 类提高开发效率
  2. 响应式设计:内置的响应式修饰符
  3. 组件化:通过抽象创建可复用的组件
  4. 自定义配置:灵活的主题定制能力
  5. 性能优化:生产环境自动移除未使用的样式

掌握 Tailwind CSS,你就能快速构建出美观、响应式的现代用户界面!


Tailwind CSS 是现代前端开发的强大工具,值得深入学习和实践。