tailwind-css

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Tailwind CSS 4.x

Tailwind CSS 4.x

Platform: Web (Tailwind CSS 4.x). For mobile styling, see the nativewind skill (Tailwind 3.x for React Native).
平台: Web(Tailwind CSS 4.x)。如需移动端样式方案,请查看nativewind技能(适用于React Native的Tailwind 3.x)。

Overview

概述

Utility-first CSS framework for rapid UI development. Tailwind CSS 4.x introduces a CSS-first configuration approach, automatic content detection, and improved performance with a new engine.
Install:
pnpm add -D tailwindcss @tailwindcss/vite
面向快速UI开发的优先实用类CSS框架。Tailwind CSS 4.x 引入了CSS优先的配置方式、自动内容检测功能,并通过全新引擎提升了性能。
安装:
pnpm add -D tailwindcss @tailwindcss/vite

Key Changes in v4

v4 主要变更

Tailwind CSS 4.x is fundamentally different from v3:
  • CSS-first configuration - Use
    @theme
    in CSS instead of
    tailwind.config.js
  • Single import - Use
    @import "tailwindcss"
    instead of separate directives
  • Automatic content detection - No
    content
    array needed
  • New color system - OKLCH colors with wide gamut support
  • Built-in Vite plugin -
    @tailwindcss/vite
    for optimal integration
Tailwind CSS 4.x 与v3版本存在本质区别:
  • CSS优先配置 - 在CSS中使用
    @theme
    替代
    tailwind.config.js
  • 单一导入 - 使用
    @import "tailwindcss"
    替代多个独立指令
  • 自动内容检测 - 无需配置
    content
    数组
  • 全新颜色系统 - 支持广色域的OKLCH颜色
  • 内置Vite插件 -
    @tailwindcss/vite
    实现最优集成

Workflows

工作流程

Setting up Tailwind v4:
  1. Install dependencies:
    pnpm add -D tailwindcss @tailwindcss/vite
  2. Add Vite plugin to
    vite.config.ts
  3. Create
    index.css
    with
    @import "tailwindcss"
  4. Customize theme with
    @theme
    directive
  5. Test build process and verify styles load
Creating components:
  1. Start with semantic HTML structure
  2. Apply utility classes for layout (flex, grid)
  3. Add spacing utilities (p-, m-, gap-*)
  4. Style with color, typography, borders
  5. Add responsive variants (sm:, md:, lg:)
  6. Test in multiple viewports
Custom theme:
  1. Define design tokens using
    @theme
    in CSS
  2. Add custom colors, spacing, fonts
  3. Create semantic color aliases
  4. Verify tokens work across components
Tailwind v4 搭建步骤:
  1. 安装依赖:
    pnpm add -D tailwindcss @tailwindcss/vite
  2. vite.config.ts
    中添加Vite插件
  3. 创建
    index.css
    并添加
    @import "tailwindcss"
  4. 使用
    @theme
    指令自定义主题
  5. 测试构建流程并验证样式加载情况
组件创建流程:
  1. 从语义化HTML结构开始
  2. 应用布局实用类(flex、grid)
  3. 添加间距实用类(p-, m-, gap-*)
  4. 设置颜色、排版、边框样式
  5. 添加响应式变体(sm:, md:, lg:)
  6. 在多视口下测试
自定义主题:
  1. 在CSS中使用
    @theme
    定义设计令牌
  2. 添加自定义颜色、间距、字体
  3. 创建语义化颜色别名
  4. 验证令牌在所有组件中正常工作

Configuration

配置

Vite Configuration

Vite 配置

typescript
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  plugins: [
    react(),
    tailwindcss(),
  ],
});
typescript
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  plugins: [
    react(),
    tailwindcss(),
  ],
});

CSS Entry Point

CSS 入口文件

css
/* src/index.css */
@import "tailwindcss";

/* Theme customization with @theme */
@theme {
  /* Colors */
  --color-primary: oklch(0.6 0.2 250);
  --color-secondary: oklch(0.6 0.15 300);
  --color-success: oklch(0.7 0.2 150);
  --color-warning: oklch(0.8 0.15 85);
  --color-danger: oklch(0.6 0.25 25);

  /* Fonts */
  --font-sans: "Inter", system-ui, sans-serif;
  --font-mono: "Fira Code", monospace;

  /* Custom spacing */
  --spacing-128: 32rem;
  --spacing-144: 36rem;

  /* Custom animations */
  --animate-fade-in: fade-in 0.3s ease-out;
  --animate-slide-up: slide-up 0.3s ease-out;
}

/* Keyframe definitions */
@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes slide-up {
  from { transform: translateY(20px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}
css
/* src/index.css */
@import "tailwindcss";

/* 使用@theme自定义主题 */
@theme {
  /* 颜色 */
  --color-primary: oklch(0.6 0.2 250);
  --color-secondary: oklch(0.6 0.15 300);
  --color-success: oklch(0.7 0.2 150);
  --color-warning: oklch(0.8 0.15 85);
  --color-danger: oklch(0.6 0.25 25);

  /* 字体 */
  --font-sans: "Inter", system-ui, sans-serif;
  --font-mono: "Fira Code", monospace;

  /* 自定义间距 */
  --spacing-128: 32rem;
  --spacing-144: 36rem;

  /* 自定义动画 */
  --animate-fade-in: fade-in 0.3s ease-out;
  --animate-slide-up: slide-up 0.3s ease-out;
}

/* 关键帧定义 */
@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes slide-up {
  from { transform: translateY(20px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

Design Token Integration

设计令牌集成

css
/* src/index.css */
@import "tailwindcss";

@theme {
  /* Brand colors using OKLCH for wide gamut */
  --color-brand-primary: oklch(0.55 0.2 250);
  --color-brand-secondary: oklch(0.55 0.15 300);
  --color-brand-accent: oklch(0.65 0.25 330);

  /* Semantic colors */
  --color-success: oklch(0.7 0.2 150);
  --color-warning: oklch(0.8 0.15 85);
  --color-error: oklch(0.6 0.25 25);
  --color-info: oklch(0.65 0.15 220);

  /* Neutral scale */
  --color-gray-50: oklch(0.98 0 0);
  --color-gray-100: oklch(0.96 0 0);
  --color-gray-200: oklch(0.92 0 0);
  --color-gray-300: oklch(0.87 0 0);
  --color-gray-400: oklch(0.7 0 0);
  --color-gray-500: oklch(0.55 0 0);
  --color-gray-600: oklch(0.45 0 0);
  --color-gray-700: oklch(0.37 0 0);
  --color-gray-800: oklch(0.27 0 0);
  --color-gray-900: oklch(0.2 0 0);
  --color-gray-950: oklch(0.13 0 0);

  /* Typography scale */
  --font-size-xs: 0.75rem;
  --font-size-sm: 0.875rem;
  --font-size-base: 1rem;
  --font-size-lg: 1.125rem;
  --font-size-xl: 1.25rem;
  --font-size-2xl: 1.5rem;
  --font-size-3xl: 1.875rem;
  --font-size-4xl: 2.25rem;
}
css
/* src/index.css */
@import "tailwindcss";

@theme {
  /* 使用OKLCH广色域的品牌颜色 */
  --color-brand-primary: oklch(0.55 0.2 250);
  --color-brand-secondary: oklch(0.55 0.15 300);
  --color-brand-accent: oklch(0.65 0.25 330);

  /* 语义化颜色 */
  --color-success: oklch(0.7 0.2 150);
  --color-warning: oklch(0.8 0.15 85);
  --color-error: oklch(0.6 0.25 25);
  --color-info: oklch(0.65 0.15 220);

  /* 中性色阶 */
  --color-gray-50: oklch(0.98 0 0);
  --color-gray-100: oklch(0.96 0 0);
  --color-gray-200: oklch(0.92 0 0);
  --color-gray-300: oklch(0.87 0 0);
  --color-gray-400: oklch(0.7 0 0);
  --color-gray-500: oklch(0.55 0 0);
  --color-gray-600: oklch(0.45 0 0);
  --color-gray-700: oklch(0.37 0 0);
  --color-gray-800: oklch(0.27 0 0);
  --color-gray-900: oklch(0.2 0 0);
  --color-gray-950: oklch(0.13 0 0);

  /* 排版尺寸 */
  --font-size-xs: 0.75rem;
  --font-size-sm: 0.875rem;
  --font-size-base: 1rem;
  --font-size-lg: 1.125rem;
  --font-size-xl: 1.25rem;
  --font-size-2xl: 1.5rem;
  --font-size-3xl: 1.875rem;
  --font-size-4xl: 2.25rem;
}

Responsive Design

响应式设计

Breakpoints

断点

tsx
// Default breakpoints (mobile-first)
// sm: 640px   - Small tablets, large phones
// md: 768px   - Tablets
// lg: 1024px  - Laptops
// xl: 1280px  - Desktops
// 2xl: 1536px - Large desktops

// Mobile-first approach
<div className="w-full sm:w-1/2 lg:w-1/3 xl:w-1/4">
  Responsive width
</div>

// Stack on mobile, grid on desktop
<div className="flex flex-col md:flex-row gap-4">
  <div className="w-full md:w-1/2">Left</div>
  <div className="w-full md:w-1/2">Right</div>
</div>

// Hide/show at breakpoints
<div className="hidden lg:block">Desktop only</div>
<div className="block lg:hidden">Mobile only</div>

// Responsive typography
<h1 className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl">
  Scales with viewport
</h1>
tsx
// 默认断点(移动端优先)
// sm: 640px   - 小平板、大屏手机
// md: 768px   - 平板
// lg: 1024px  - 笔记本电脑
// xl: 1280px  - 桌面端
// 2xl: 1536px - 大屏桌面端

// 移动端优先示例
<div className="w-full sm:w-1/2 lg:w-1/3 xl:w-1/4">
  响应式宽度
</div>

// 移动端堆叠,桌面端网格布局
<div className="flex flex-col md:flex-row gap-4">
  <div className="w-full md:w-1/2">左侧</div>
  <div className="w-full md:w-1/2">右侧</div>
</div>

// 断点条件下显示/隐藏
<div className="hidden lg:block">仅桌面端显示</div>
<div className="block lg:hidden">仅移动端显示</div>

// 响应式排版
<h1 className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl">
  随视口尺寸缩放
</h1>

Custom Breakpoints

自定义断点

css
/* In @theme block */
@theme {
  --breakpoint-demo: 1440px;
}
tsx
// Usage
<div className="hidden demo:block">Demo mode only</div>
css
/* 在@theme块中定义 */
@theme {
  --breakpoint-demo: 1440px;
}
tsx
// 使用示例
<div className="hidden demo:block">仅演示模式显示</div>

Dark Mode

暗色模式

Class-based Dark Mode

基于类的暗色模式

css
/* src/index.css */
@import "tailwindcss";

/* Dark mode variants */
@variant dark (&:where(.dark, .dark *));
tsx
// App-level dark mode toggle
import { useEffect, useState } from 'react';

function App() {
  const [isDark, setIsDark] = useState(false);

  useEffect(() => {
    document.documentElement.classList.toggle('dark', isDark);
  }, [isDark]);

  return (
    <div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">
      <button onClick={() => setIsDark(!isDark)}>
        Toggle Dark Mode
      </button>
    </div>
  );
}

// Component with dark mode styles
<div className="bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-700">
  <h2 className="text-gray-900 dark:text-gray-100">Title</h2>
  <p className="text-gray-600 dark:text-gray-400">Description</p>
</div>
css
/* src/index.css */
@import "tailwindcss";

/* 暗色模式变体 */
@variant dark (&:where(.dark, .dark *));
tsx
// 应用级暗色模式切换
import { useEffect, useState } from 'react';

function App() {
  const [isDark, setIsDark] = useState(false);

  useEffect(() => {
    document.documentElement.classList.toggle('dark', isDark);
  }, [isDark]);

  return (
    <div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">
      <button onClick={() => setIsDark(!isDark)}>
        切换暗色模式
      </button>
    </div>
  );
}

// 带暗色模式样式的组件
<div className="bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-700">
  <h2 className="text-gray-900 dark:text-gray-100">标题</h2>
  <p className="text-gray-600 dark:text-gray-400">描述</p>
</div>

Component Patterns

组件模式

Cards

卡片

tsx
// Basic card
<div className="rounded-lg border border-gray-200 bg-white p-6 shadow-sm">
  <h3 className="text-lg font-semibold text-gray-900">Card Title</h3>
  <p className="mt-2 text-sm text-gray-600">Card description</p>
</div>

// Interactive card with hover
<div className="rounded-lg border border-gray-200 bg-white p-6 shadow-sm transition-all hover:shadow-md hover:scale-[1.02] cursor-pointer">
  <h3 className="text-lg font-semibold text-gray-900">Clickable Card</h3>
</div>

// Card with header and footer
<div className="rounded-lg border border-gray-200 bg-white overflow-hidden">
  <div className="border-b border-gray-200 bg-gray-50 px-6 py-4">
    <h3 className="text-lg font-semibold text-gray-900">Header</h3>
  </div>
  <div className="p-6">
    <p className="text-sm text-gray-600">Content</p>
  </div>
  <div className="border-t border-gray-200 bg-gray-50 px-6 py-4">
    <button className="text-sm font-medium text-blue-600 hover:text-blue-700">
      Action
    </button>
  </div>
</div>
tsx
// 基础卡片
<div className="rounded-lg border border-gray-200 bg-white p-6 shadow-sm">
  <h3 className="text-lg font-semibold text-gray-900">卡片标题</h3>
  <p className="mt-2 text-sm text-gray-600">卡片描述</p>
</div>

// 带悬停效果的交互式卡片
<div className="rounded-lg border border-gray-200 bg-white p-6 shadow-sm transition-all hover:shadow-md hover:scale-[1.02] cursor-pointer">
  <h3 className="text-lg font-semibold text-gray-900">可点击卡片</h3>
</div>

// 带头部和底部的卡片
<div className="rounded-lg border border-gray-200 bg-white overflow-hidden">
  <div className="border-b border-gray-200 bg-gray-50 px-6 py-4">
    <h3 className="text-lg font-semibold text-gray-900">头部</h3>
  </div>
  <div className="p-6">
    <p className="text-sm text-gray-600">内容</p>
  </div>
  <div className="border-t border-gray-200 bg-gray-50 px-6 py-4">
    <button className="text-sm font-medium text-blue-600 hover:text-blue-700">
      操作
    </button>
  </div>
</div>

Buttons

按钮

tsx
// Primary button
<button className="rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 active:bg-blue-800 disabled:opacity-50 disabled:cursor-not-allowed transition-colors">
  Primary
</button>

// Secondary button
<button className="rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 active:bg-gray-100 transition-colors">
  Secondary
</button>

// Ghost button
<button className="rounded-md px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors">
  Ghost
</button>

// Button sizes via extractable pattern
const buttonSizes = {
  sm: 'px-3 py-1.5 text-xs',
  md: 'px-4 py-2 text-sm',
  lg: 'px-6 py-3 text-base',
};

<button className={`rounded-md bg-blue-600 text-white ${buttonSizes.lg}`}>
  Large Button
</button>
tsx
// 主按钮
<button className="rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 active:bg-blue-800 disabled:opacity-50 disabled:cursor-not-allowed transition-colors">
  主按钮
</button>

// 次按钮
<button className="rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 active:bg-gray-100 transition-colors">
  次按钮
</button>

// 幽灵按钮
<button className="rounded-md px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors">
  幽灵按钮
</button>

// 可提取的按钮尺寸模式
const buttonSizes = {
  sm: 'px-3 py-1.5 text-xs',
  md: 'px-4 py-2 text-sm',
  lg: 'px-6 py-3 text-base',
};

<button className={`rounded-md bg-blue-600 text-white ${buttonSizes.lg}`}>
  大尺寸按钮
</button>

Badges

徽章

tsx
// Status badges
<span className="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800">
  Success
</span>

<span className="inline-flex items-center rounded-full bg-yellow-100 px-2.5 py-0.5 text-xs font-medium text-yellow-800">
  Warning
</span>

<span className="inline-flex items-center rounded-full bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800">
  Error
</span>
tsx
// 状态徽章
<span className="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800">
  成功
</span>

<span className="inline-flex items-center rounded-full bg-yellow-100 px-2.5 py-0.5 text-xs font-medium text-yellow-800">
  警告
</span>

<span className="inline-flex items-center rounded-full bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800">
  错误
</span>

Form Inputs

表单输入框

tsx
// Text input
<div className="space-y-1">
  <label htmlFor="email" className="block text-sm font-medium text-gray-700">
    Email
  </label>
  <input
    type="email"
    id="email"
    className="block w-full rounded-md border border-gray-300 px-3 py-2 text-sm placeholder-gray-400 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
    placeholder="you@example.com"
  />
</div>

// Input with error state
<input
  type="text"
  className="block w-full rounded-md border border-red-300 px-3 py-2 text-sm shadow-sm focus:border-red-500 focus:outline-none focus:ring-1 focus:ring-red-500"
/>
<p className="mt-1 text-xs text-red-600">This field is required</p>
tsx
// 文本输入框
<div className="space-y-1">
  <label htmlFor="email" className="block text-sm font-medium text-gray-700">
    邮箱
  </label>
  <input
    type="email"
    id="email"
    className="block w-full rounded-md border border-gray-300 px-3 py-2 text-sm placeholder-gray-400 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
    placeholder="you@example.com"
  />
</div>

// 带错误状态的输入框
<input
  type="text"
  className="block w-full rounded-md border border-red-300 px-3 py-2 text-sm shadow-sm focus:border-red-500 focus:outline-none focus:ring-1 focus:ring-red-500"
/>
<p className="mt-1 text-xs text-red-600">此字段为必填项</p>

Grid Layouts

网格布局

tsx
// Auto-fit responsive grid
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
  {items.map(item => (
    <div key={item.id} className="rounded-lg border border-gray-200 p-4">
      {item.content}
    </div>
  ))}
</div>

// Sidebar layout
<div className="flex gap-6">
  <aside className="w-64 shrink-0">Sidebar</aside>
  <main className="flex-1">Main content</main>
</div>

// Dashboard grid
<div className="grid grid-cols-12 gap-4">
  <div className="col-span-12 lg:col-span-8">Main</div>
  <div className="col-span-12 lg:col-span-4">Sidebar</div>
</div>
tsx
// 自动适配的响应式网格
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
  {items.map(item => (
    <div key={item.id} className="rounded-lg border border-gray-200 p-4">
      {item.content}
    </div>
  ))}
</div>

// 侧边栏布局
<div className="flex gap-6">
  <aside className="w-64 shrink-0">侧边栏</aside>
  <main className="flex-1">主内容</main>
</div>

// 仪表盘网格
<div className="grid grid-cols-12 gap-4">
  <div className="col-span-12 lg:col-span-8">主区域</div>
  <div className="col-span-12 lg:col-span-4">侧边栏</div>
</div>

Advanced Patterns

高级模式

Arbitrary Values

任意值

tsx
// Custom values with []
<div className="top-[117px]">Custom positioning</div>
<div className="bg-[#1da1f2]">Custom color</div>
<div className="grid-cols-[1fr_500px_2fr]">Custom grid</div>

// CSS variables
<div className="bg-[var(--brand-color)]">CSS variable</div>

// Calc expressions
<div className="w-[calc(100%-2rem)]">Dynamic width</div>
tsx
// 使用[]定义自定义值
<div className="top-[117px]">自定义定位</div>
<div className="bg-[#1da1f2]">自定义颜色</div>
<div className="grid-cols-[1fr_500px_2fr]">自定义网格</div>

// CSS变量
<div className="bg-[var(--brand-color)]">CSS变量</div>

// 计算表达式
<div className="w-[calc(100%-2rem)]">动态宽度</div>

Custom Utilities with @utility

使用@utility创建自定义实用类

css
/* src/index.css */
@import "tailwindcss";

@utility text-balance {
  text-wrap: balance;
}

@utility scrollbar-hide {
  -ms-overflow-style: none;
  scrollbar-width: none;
  &::-webkit-scrollbar {
    display: none;
  }
}
tsx
// Usage
<p className="text-balance">Balanced text wrapping</p>
<div className="scrollbar-hide overflow-auto">Hidden scrollbar</div>
css
/* src/index.css */
@import "tailwindcss";

@utility text-balance {
  text-wrap: balance;
}

@utility scrollbar-hide {
  -ms-overflow-style: none;
  scrollbar-width: none;
  &::-webkit-scrollbar {
    display: none;
  }
}
tsx
// 使用示例
<p className="text-balance">文本均衡换行</p>
<div className="scrollbar-hide overflow-auto">隐藏滚动条</div>

Variant Modifiers

变体修饰符

tsx
// Group hover
<div className="group hover:bg-gray-100">
  <h3 className="group-hover:text-blue-600">Hover parent to change me</h3>
</div>

// Peer (sibling state)
<input type="checkbox" className="peer" />
<label className="peer-checked:text-blue-600">Label changes when checked</label>

// First/last child
<ul>
  <li className="first:rounded-t-lg last:rounded-b-lg border-b last:border-b-0">Item</li>
</ul>

// Odd/even
<tr className="odd:bg-gray-50 even:bg-white">
  <td>Table cell</td>
</tr>

// Data attributes
<div data-state="active" className="data-[state=active]:bg-blue-100">
  Active state
</div>
tsx
// 组悬停
<div className="group hover:bg-gray-100">
  <h3 className="group-hover:text-blue-600">悬停父元素以改变本元素样式</h3>
</div>

// 同级元素状态关联(peer)
<input type="checkbox" className="peer" />
<label className="peer-checked:text-blue-600">勾选后标签变色</label>

// 第一个/最后一个子元素
<ul>
  <li className="first:rounded-t-lg last:rounded-b-lg border-b last:border-b-0">列表项</li>
</ul>

// 奇数/偶数行
<tr className="odd:bg-gray-50 even:bg-white">
  <td>表格单元格</td>
</tr>

// 数据属性
<div data-state="active" className="data-[state=active]:bg-blue-100">
  激活状态
</div>

Migration from v3

从v3版本迁移

Key Differences

核心差异

v3 Patternv4 Pattern
tailwind.config.js
@theme
in CSS
@tailwind base;
etc.
@import "tailwindcss"
content: [...]
Automatic detection
PostCSS plugin
@tailwindcss/vite
plugin
@apply
in CSS
Still supported, prefer utilities
v3 模式v4 模式
tailwind.config.js
CSS中的
@theme
@tailwind base;
等指令
@import "tailwindcss"
content: [...]
自动检测
PostCSS插件
@tailwindcss/vite
插件
CSS中的
@apply
仍支持,但优先使用实用类

Migration Steps

迁移步骤

  1. Install new packages:
    pnpm add -D tailwindcss @tailwindcss/vite
  2. Replace PostCSS config with Vite plugin
  3. Replace
    @tailwind
    directives with
    @import "tailwindcss"
  4. Move theme customizations from
    tailwind.config.js
    to
    @theme
    in CSS
  5. Remove
    content
    array (auto-detected in v4)
  6. Test all components for any breaking changes
  1. 安装新包:
    pnpm add -D tailwindcss @tailwindcss/vite
  2. 替换PostCSS配置为Vite插件
  3. @tailwind
    指令替换为
    @import "tailwindcss"
  4. 将主题自定义内容从
    tailwind.config.js
    迁移至CSS中的
    @theme
  5. 移除
    content
    数组(v4中自动检测)
  6. 测试所有组件是否存在兼容性问题

Best Practices

最佳实践

  • Mobile-first approach - Start with base styles, add responsive variants
  • Use semantic color names - primary, secondary, danger via
    @theme
  • Use
    @theme
    for design tokens
    - Colors, spacing, fonts in CSS
  • Keep classes organized - Layout → Spacing → Colors → Typography → States
  • Use arbitrary values sparingly - Prefer theme tokens
  • Prefer utility classes over custom CSS for maintainability
  • Group hover/focus states with group-* and peer-* utilities
  • Use the Vite plugin -
    @tailwindcss/vite
    for best performance
  • 移动端优先 - 从基础样式开始,逐步添加响应式变体
  • 使用语义化颜色名称 - 通过
    @theme
    定义primary、secondary、danger等颜色
  • 使用@theme管理设计令牌 - 颜色、间距、字体统一在CSS中配置
  • 保持类名有序 - 布局 → 间距 → 颜色 → 排版 → 状态的顺序组织类名
  • 谨慎使用任意值 - 优先使用主题令牌
  • 优先使用实用类 - 相比自定义CSS,实用类更易维护
  • **使用group-和peer-管理状态 - 统一处理父子/同级元素的交互状态
  • 使用Vite插件 -
    @tailwindcss/vite
    能提供最佳性能

Anti-Patterns

反模式

  • ❌ Using
    tailwind.config.js
    for simple customization (use
    @theme
    )
  • ❌ Using
    @tailwind
    directives (use
    @import "tailwindcss"
    )
  • ❌ Manually configuring
    content
    array (auto-detected in v4)
  • ❌ Using PostCSS plugin with Vite (use
    @tailwindcss/vite
    )
  • ❌ Desktop-first responsive design (not mobile-friendly)
  • ❌ Inline styles mixed with Tailwind (inconsistent)
  • ❌ Ignoring accessibility (missing focus states)
  • ❌ Hardcoding colors instead of using theme tokens
  • ❌ 简单自定义仍使用
    tailwind.config.js
    (应使用
    @theme
  • ❌ 仍使用
    @tailwind
    指令(应使用
    @import "tailwindcss"
  • ❌ 手动配置
    content
    数组(v4中自动检测)
  • ❌ Vite项目中使用PostCSS插件(应使用
    @tailwindcss/vite
  • ❌ 桌面端优先的响应式设计(不符合移动端友好原则)
  • ❌ Tailwind类与内联样式混用(样式不一致)
  • ❌ 忽略可访问性(缺少焦点状态样式)
  • ❌ 硬编码颜色值(应使用主题令牌)

Feedback Loops

反馈验证

Build verification:
bash
undefined
构建验证:
bash
undefined

Check generated CSS size

检查生成的CSS文件大小

pnpm build
pnpm build

Inspect dist/assets/*.css file size

查看dist/assets/*.css文件大小

Target: < 50KB for production

目标:生产环境下小于50KB


**Development mode:**
```bash

**开发模式验证:**
```bash

Watch for changes

监听文件变更

pnpm dev
pnpm dev

Verify new utilities are generated

验证新实用类是否生成

Check browser console for Tailwind warnings

检查浏览器控制台的Tailwind警告信息


**Accessibility check:**
```tsx
// Test focus states
// Tab through interactive elements
// Verify focus:ring-* utilities visible
// Check color contrast with devtools

**可访问性检查:**
```tsx
// 测试焦点状态
// 按Tab键遍历交互元素
// 验证focus:ring-*实用类可见
// 使用开发者工具检查颜色对比度