跳转到内容

Tailwind CSS v4 实战指南 2026

Tailwind CSS v4

🎨 什么是 Tailwind CSS? Tailwind CSS 是全球最流行的 Utility-First CSS 框架。v4 版本用 Rust 重写了引擎(Oxide),引入了 CSS-first 配置体系,让开发体验和构建速度都实现了质的飞跃。不需要写一行自定义 CSS,就能构建出完全定制化的现代 UI。

本文将带你从 0 到 1 掌握 Tailwind CSS v4:

  • ✅ v4 核心变化与新特性
  • ✅ Vite + Tailwind v4 项目搭建
  • ✅ CSS-first 设计系统定制
  • ✅ 响应式布局实战
  • ✅ 组件构建完整代码
  • ✅ 暗色模式与动画效果
  • ✅ 三个实战项目案例
  • ✅ 性能优化与最佳实践
  • ✅ 常见问题与解决方案

一、Tailwind CSS v4 核心变化

1.1 v4 vs v3 关键差异

Tailwind CSS v4 是一次架构级重写,不是简单的版本升级。

特性v3v4影响
配置方式tailwind.config.jsCSS @theme 指令告别 JS 配置文件
构建引擎JavaScriptRust (Oxide)速度提升 10 倍+
内容检测手动配置 content自动检测零配置起步
Vite 集成PostCSS 插件原生 Vite 插件更快的热更新
颜色空间HEX/RGBOKLCH更均匀的色彩感知
安装方式3 步配置1 行导入极简上手
容器查询需要插件内置支持开箱即用
3D 变换不支持内置支持rotate-x-45
自定义变体addVariant()@variant 指令纯 CSS 扩展

1.2 为什么选择 Tailwind CSS

传统 CSS 框架(Bootstrap、Bulma)提供预定义组件,修改样式需要覆盖大量 CSS。Tailwind 走了另一条路——只提供原子化工具类,组合即设计。

Tailwind 的核心理念:

<!-- 传统 CSS -->
<button class="btn btn-primary">按钮</button>
<!-- 还需要写 .btn .btn-primary 的 CSS -->

<!-- Tailwind CSS -->
<button class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-lg transition-colors">
  按钮
</button>
<!-- 不需要写任何自定义 CSS -->

优势一览:

优势说明
🔒 一致性所有间距、颜色、字号都来自设计系统,不会出现 margin: 13px 这种随意值
开发速度不用切换 HTML/CSS 文件,不用想类名,直接在 HTML 中写样式
📦 体积小只生成用到的 CSS,生产环境通常 < 15KB
🔄 可维护改样式不用搜索 CSS 文件,直接改 HTML 中的类名
🎯 无命名冲突不存在 CSS 类名冲突问题

1.3 适合与不适合的场景

适合 ✅不太适合 ❌
新项目从零开始已有大量自定义 CSS 的遗留项目
团队希望统一设计规范需要高度定制化动画的创意网站
Vite/Vue/React 现代技术栈纯静态 HTML 页面(可用 CDN 但体验打折)
需要快速迭代原型设计师需要直接写 CSS 的工作流
组件化开发模式

二、环境搭建

2.1 Vite + Tailwind v4 项目初始化

v4 的安装比 v3 简单得多——一行导入即可。

bash
# 1. 创建 Vite 项目
pnpm create vite my-app --template vue-ts
cd my-app
pnpm install

# 2. 安装 Tailwind CSS v4
pnpm add tailwindcss @tailwindcss/vite

# 3. 配置 Vite 插件
# 修改 vite.config.ts

vite.config.ts

typescript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import tailwindcss from '@tailwindcss/vite'

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

src/style.css

css
/* 一行导入,完成!不需要 tailwind.config.js */
@import "tailwindcss";

src/main.ts

typescript
import { createApp } from 'vue'
import App from './App.vue'
import './style.css'

createApp(App).mount('#app')

就这样,三步完成。对比 v3 需要的 tailwind.config.js + postcss.config.js + content 路径配置,v4 极大地简化了上手流程。

2.2 与 v3 项目迁移

如果你有现成的 v3 项目,迁移到 v4 只需几步:

bash
# 升级依赖
pnpm remove tailwindcss postcss autoprefixer
pnpm add tailwindcss @tailwindcss/vite

# 删除旧配置文件
rm tailwind.config.js postcss.config.js

修改 vite.config.ts(同上),修改 CSS 入口文件:

css
/* 旧写法 (v3) */
/* @tailwind base; */
/* @tailwind components; */
/* @tailwind utilities; */

/* 新写法 (v4) */
@import "tailwindcss";

/* 如果有自定义配置,用 @theme 迁移 */
@theme {
  /* 旧 tailwind.config.js 中的 theme.extend 内容迁移到这里 */
  --color-brand: #3b82f6;
  --font-display: "Inter", sans-serif;
}

2.3 VS Code 开发环境

插件说明
Tailwind CSS IntelliSense官方插件,提供类名自动补全、悬停预览、Lint 检查
Tailwind Sort自动排序类名,保持代码整洁
PostCSS Language Support如果还有 PostCSS 语法需要支持

推荐 VS Code 配置(.vscode/settings.json):

json
{
  "tailwindCSS.includeLanguages": {
    "vue": "html",
    "svelte": "html"
  },
  "tailwindCSS.experimental.classRegex": [
    "tw`([^`]*)",
    "tw\\(\"([^\"]*)\"",
    "className=\"([^\"]*)"
  ],
  "editor.quickSuggestions": {
    "strings": true
  },
  "files.associations": {
    "*.css": "tailwindcss"
  }
}

2.4 CDN 方式(快速原型)

如果只是想快速试用,不需要构建工具:

html
<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
  <h1 class="text-3xl font-bold text-blue-500">Hello Tailwind v4!</h1>
</body>
</html>

⚠️ 注意: CDN 版本仅用于开发原型,生产环境请务必使用构建工具方式,以获得 Tree Shaking 和最小化 CSS 体积。


三、CSS-first 设计系统

3.1 @theme 指令

v4 最大的变化是用 CSS 中的 @theme 指令替代了 JS 配置文件。所有设计 token 都在 CSS 中定义。

css
@import "tailwindcss";

@theme {
  /* 自定义颜色 */
  --color-brand-50: #eff6ff;
  --color-brand-100: #dbeafe;
  --color-brand-500: #3b82f6;
  --color-brand-600: #2563eb;
  --color-brand-700: #1d4ed8;
  --color-brand-900: #1e3a8a;

  /* 自定义字体 */
  --font-sans: "Inter", "Noto Sans SC", sans-serif;
  --font-mono: "JetBrains Mono", monospace;

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

  /* 自定义断点 */
  --breakpoint-3xl: 1920px;

  /* 自定义动画 */
  --animate-fade-in: fade-in 0.5s ease-out;

  @keyframes fade-in {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
  }
}

定义后,Tailwind 会自动生成对应的工具类:

html
<!-- 自动可用 -->
<div class="bg-brand-500 text-white font-sans p-128 3xl:block animate-fade-in">
  自定义设计 token
</div>

3.2 颜色系统

v4 默认使用 OKLCH 色彩空间,色彩感知更均匀。

css
@theme {
  /* 使用 OKLCH 定义颜色(推荐) */
  --color-primary: oklch(0.6 0.2 250);
  --color-success: oklch(0.7 0.15 145);
  --color-warning: oklch(0.75 0.18 85);
  --color-danger: oklch(0.6 0.2 25);

  /* 也可以用 HEX/RGB */
  --color-accent: #8b5cf6;
}

默认调色板速查:

色系关键值用途
slateslate-500/700/900文字、深色背景
graygray-100/500/900中性背景、边框
redred-500/600错误、删除
orangeorange-400/500警告、高亮
amberamber-400/500警告提示
yellowyellow-400注意提示
greengreen-500/600成功、确认
tealteal-500/600信息提示
blueblue-500/600主色、链接
indigoindigo-500/600品牌主色
purplepurple-500/600品牌辅色
pinkpink-400/500强调装饰

3.3 间距与排版

Tailwind 的间距系统基于 4px 基准值(1 = 0.25rem = 4px)。

类名常见用途
p-1 / m-14px紧凑间距
p-2 / m-28px小间距
p-4 / m-416px标准间距
p-6 / m-624px中等间距
p-8 / m-832px大间距
p-12 / m-1248px区块间距
p-16 / m-1664px页面级间距
gap-416pxFlex/Grid 间距

排版工具类:

html
<!-- 字号 -->
<p class="text-xs text-sm text-base text-lg text-xl text-2xl text-3xl">
<p class="text-4xl text-5xl text-6xl text-7xl">

<!-- 字重 -->
<p class="font-thin font-light font-normal font-medium font-semibold font-bold font-extrabold">

<!-- 行高 -->
<p class="leading-none leading-tight leading-normal leading-relaxed leading-loose">

<!-- 字间距 -->
<p class="tracking-tight tracking-normal tracking-wide tracking-wider">

<!-- 文字对齐 -->
<p class="text-left text-center text-right text-justify">

3.4 响应式断点

v4 默认断点与 v3 一致,但可以通过 @theme 自定义:

前缀断点典型设备
(无)0px所有设备
sm:640px大手机横屏
md:768px平板竖屏
lg:1024px平板横屏 / 小笔电
xl:1280px桌面显示器
2xl:1536px大屏显示器
css
/* 自定义添加 3xl 断点 */
@theme {
  --breakpoint-3xl: 1920px;
}
html
<!-- 移动端 1 列,平板 2 列,桌面 3 列,大屏 4 列 -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 3xl:grid-cols-4">
  ...
</div>

四、布局实战

4.1 Flexbox 布局

html
<!-- 水平居中 -->
<div class="flex justify-center">
  <div class="bg-blue-500 p-4">居中</div>
</div>

<!-- 两端对齐 -->
<div class="flex justify-between items-center">
  <div class="text-lg font-bold">Logo</div>
  <nav class="flex gap-4">
    <a href="#" class="hover:text-blue-500">首页</a>
    <a href="#" class="hover:text-blue-500">关于</a>
    <a href="#" class="hover:text-blue-500">联系</a>
  </nav>
</div>

<!-- 垂直居中 -->
<div class="flex items-center min-h-screen">
  <div class="mx-auto text-center">
    <h1 class="text-4xl font-bold">垂直水平居中</h1>
  </div>
</div>

<!-- 等宽分布 -->
<div class="flex">
  <div class="flex-1 bg-red-200 p-4">1</div>
  <div class="flex-1 bg-green-200 p-4">2</div>
  <div class="flex-1 bg-blue-200 p-4">3</div>
</div>

<!-- 换行 -->
<div class="flex flex-wrap gap-4">
  <div class="w-64 bg-gray-100 p-4">卡片 1</div>
  <div class="w-64 bg-gray-100 p-4">卡片 2</div>
  <div class="w-64 bg-gray-100 p-4">卡片 3</div>
</div>

4.2 Grid 布局

html
<!-- 基础网格 -->
<div class="grid grid-cols-3 gap-4">
  <div class="bg-gray-100 p-4">1</div>
  <div class="bg-gray-100 p-4">2</div>
  <div class="bg-gray-100 p-4">3</div>
</div>

<!-- 响应式网格 -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
  <!-- 卡片内容 -->
</div>

<!-- 跨列 -->
<div class="grid grid-cols-3 gap-4">
  <div class="col-span-2 bg-blue-100 p-4">占 2 列</div>
  <div class="bg-gray-100 p-4">占 1 列</div>
  <div class="col-span-3 bg-green-100 p-4">占 3 列</div>
</div>

<!-- 12 列网格(类似 Bootstrap) -->
<div class="grid grid-cols-12 gap-4">
  <div class="col-span-12 md:col-span-8 bg-blue-100 p-4">主内容</div>
  <div class="col-span-12 md:col-span-4 bg-gray-100 p-4">侧边栏</div>
</div>

<!-- 自动填充 -->
<div class="grid grid-cols-[repeat(auto-fill,minmax(250px,1fr))] gap-4">
  <!-- 自动适配宽度的卡片网格 -->
</div>

4.3 定位

html
<!-- 相对 + 绝对定位 -->
<div class="relative">
  <div class="bg-white p-4">主内容</div>
  <div class="absolute top-0 right-0 bg-red-500 text-white px-2 py-1 text-xs rounded-bl-lg">
    NEW
  </div>
</div>

<!-- 固定定位 -->
<nav class="fixed top-0 left-0 right-0 bg-white shadow-md z-50">
  <!-- 固定导航栏 -->
</nav>

<!-- 粘性定位 -->
<div class="sticky top-0 bg-white/90 backdrop-blur z-40">
  <!-- 滚动时固定的标题栏 -->
</div>

<!-- 层叠 -->
<div class="z-10">底层</div>
<div class="z-20">中层</div>
<div class="z-50">顶层</div>

4.4 容器查询

v4 内置了容器查询支持,不再需要插件:

html
<!-- 父容器设置 @container -->
<div class="@container">
  <!-- 子元素根据父容器宽度响应 -->
  <div class="flex flex-col @md:flex-row gap-4">
    <div class="@md:w-1/3">侧边栏</div>
    <div class="@md:w-2/3">主内容</div>
  </div>
</div>

<!-- 容器查询断点 -->
<!-- @sm: 24rem, @md: 28rem, @lg: 32rem, @xl: 36rem, @2xl: 42rem, @3xl: 48rem -->

💡 容器查询 vs 媒体查询: 媒体查询基于视口宽度,容器查询基于父容器宽度。组件化开发中容器查询更灵活——同一个组件在不同位置可以自适应不同宽度。


五、组件构建

5.1 按钮

html
<!-- 基础按钮 -->
<button class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-lg transition-colors">
  点击
</button>

<!-- 变体:轮廓 -->
<button class="border-2 border-blue-500 text-blue-500 hover:bg-blue-500 hover:text-white font-medium py-2 px-4 rounded-lg transition-colors">
  轮廓
</button>

<!-- 变体:幽灵 -->
<button class="text-blue-500 hover:bg-blue-50 font-medium py-2 px-4 rounded-lg transition-colors">
  幽灵
</button>

<!-- 变体:危险 -->
<button class="bg-red-500 hover:bg-red-600 text-white font-medium py-2 px-4 rounded-lg transition-colors">
  删除
</button>

<!-- 尺寸 -->
<button class="text-xs px-2 py-1 rounded">超小</button>
<button class="text-sm px-3 py-1.5 rounded-md">小</button>
<button class="text-base px-4 py-2 rounded-lg">默认</button>
<button class="text-lg px-6 py-3 rounded-lg">大</button>

<!-- 带图标 -->
<button class="inline-flex items-center gap-2 bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-lg transition-colors">
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
  </svg>
  添加
</button>

<!-- 禁用状态 -->
<button disabled class="bg-gray-300 text-gray-500 font-medium py-2 px-4 rounded-lg cursor-not-allowed">
  禁用
</button>

5.2 卡片

html
<!-- 基础卡片 -->
<div class="max-w-sm rounded-xl shadow-lg overflow-hidden bg-white">
  <img class="w-full h-48 object-cover" src="/image.jpg" alt="封面">
  <div class="p-6">
    <h3 class="text-xl font-bold text-gray-900 mb-2">卡片标题</h3>
    <p class="text-gray-600 text-sm leading-relaxed">
      这是卡片的描述文字,使用 leading-relaxed 增加行高提升可读性。
    </p>
    <div class="mt-4 flex items-center gap-4">
      <span class="text-sm text-gray-500">2026-07-11</span>
      <span class="px-2 py-1 bg-blue-100 text-blue-700 text-xs rounded-full">标签</span>
    </div>
  </div>
</div>

<!-- 悬停效果卡片 -->
<div class="group max-w-sm rounded-xl shadow-md hover:shadow-xl transition-all duration-300 hover:-translate-y-1 overflow-hidden bg-white cursor-pointer">
  <div class="relative overflow-hidden">
    <img class="w-full h-48 object-cover group-hover:scale-110 transition-transform duration-500" src="/image.jpg" alt="封面">
    <div class="absolute top-3 right-3 bg-red-500 text-white text-xs px-2 py-1 rounded-full">
      热门
    </div>
  </div>
  <div class="p-6">
    <h3 class="text-lg font-bold text-gray-900 group-hover:text-blue-500 transition-colors">
      悬停看效果
    </h3>
    <p class="mt-2 text-gray-600 text-sm">鼠标悬停时卡片上浮、阴影加深、图片放大。</p>
  </div>
</div>

5.3 导航栏

html
<!-- 响应式导航栏 -->
<nav class="bg-white border-b border-gray-100 sticky top-0 z-50">
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
    <div class="flex justify-between items-center h-16">
      <!-- Logo -->
      <div class="flex items-center gap-2">
        <div class="w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center">
          <span class="text-white font-bold text-sm">T</span>
        </div>
        <span class="text-lg font-bold text-gray-900">TailwindApp</span>
      </div>

      <!-- 桌面导航 -->
      <div class="hidden md:flex items-center gap-6">
        <a href="#" class="text-gray-700 hover:text-blue-500 transition-colors text-sm font-medium">首页</a>
        <a href="#" class="text-gray-700 hover:text-blue-500 transition-colors text-sm font-medium">产品</a>
        <a href="#" class="text-gray-700 hover:text-blue-500 transition-colors text-sm font-medium">文档</a>
        <a href="#" class="text-gray-700 hover:text-blue-500 transition-colors text-sm font-medium">价格</a>
        <button class="bg-blue-500 hover:bg-blue-600 text-white text-sm font-medium px-4 py-2 rounded-lg transition-colors">
          开始使用
        </button>
      </div>

      <!-- 移动端菜单按钮 -->
      <button class="md:hidden p-2 rounded-lg hover:bg-gray-100">
        <svg class="w-6 h-6 text-gray-700" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
        </svg>
      </button>
    </div>
  </div>
</nav>

5.4 表单

html
<form class="max-w-md mx-auto space-y-6">
  <!-- 文本输入 -->
  <div>
    <label class="block text-sm font-medium text-gray-700 mb-1">用户名</label>
    <input type="text" 
           class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all"
           placeholder="请输入用户名">
  </div>

  <!-- 密码输入 -->
  <div>
    <label class="block text-sm font-medium text-gray-700 mb-1">密码</label>
    <input type="password" 
           class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all"
           placeholder="请输入密码">
  </div>

  <!-- 下拉选择 -->
  <div>
    <label class="block text-sm font-medium text-gray-700 mb-1">角色</label>
    <select class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all bg-white">
      <option>管理员</option>
      <option>编辑</option>
      <option>访客</option>
    </select>
  </div>

  <!-- 复选框 -->
  <div class="flex items-center gap-2">
    <input type="checkbox" id="remember" class="w-4 h-4 text-blue-500 rounded border-gray-300 focus:ring-blue-500">
    <label for="remember" class="text-sm text-gray-700">记住我</label>
  </div>

  <!-- 文本域 -->
  <div>
    <label class="block text-sm font-medium text-gray-700 mb-1">留言</label>
    <textarea rows="4" 
              class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all resize-none"
              placeholder="请输入留言内容"></textarea>
  </div>

  <!-- 提交按钮 -->
  <button type="submit" 
          class="w-full bg-blue-500 hover:bg-blue-600 text-white font-medium py-2.5 rounded-lg transition-colors">
    提交
  </button>
</form>

5.5 模态框

html
<!-- 模态框结构 -->
<div class="fixed inset-0 z-50 flex items-center justify-center">
  <!-- 遮罩 -->
  <div class="absolute inset-0 bg-black/50 backdrop-blur-sm"></div>
  
  <!-- 内容 -->
  <div class="relative bg-white rounded-2xl shadow-2xl max-w-lg w-full mx-4 overflow-hidden">
    <!-- 头部 -->
    <div class="flex items-center justify-between p-6 border-b border-gray-100">
      <h3 class="text-lg font-bold text-gray-900">确认操作</h3>
      <button class="text-gray-400 hover:text-gray-600 p-1 rounded-lg hover:bg-gray-100 transition-colors">
        <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
        </svg>
      </button>
    </div>
    
    <!-- 主体 -->
    <div class="p-6">
      <p class="text-gray-600 text-sm leading-relaxed">
        确定要执行此操作吗?此操作不可撤销,请谨慎确认。
      </p>
    </div>
    
    <!-- 底部 -->
    <div class="flex justify-end gap-3 p-6 bg-gray-50 border-t border-gray-100">
      <button class="px-4 py-2 text-gray-700 font-medium rounded-lg hover:bg-gray-200 transition-colors">
        取消
      </button>
      <button class="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white font-medium rounded-lg transition-colors">
        确认
      </button>
    </div>
  </div>
</div>

六、状态与动画

6.1 交互状态

html
<!-- hover: 鼠标悬停 -->
<button class="bg-blue-500 hover:bg-blue-600 transition-colors">hover</button>

<!-- focus: 聚焦 -->
<input class="border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-500 outline-none">

<!-- active: 激活(按下) -->
<button class="bg-blue-500 active:bg-blue-700 active:scale-95 transition-all">active</button>

<!-- disabled: 禁用 -->
<button disabled class="bg-blue-500 disabled:opacity-50 disabled:cursor-not-allowed">disabled</button>

<!-- group-hover: 父元素悬停时子元素响应 -->
<div class="group cursor-pointer">
  <h3 class="group-hover:text-blue-500 transition-colors">标题</h3>
  <p class="text-gray-500 group-hover:text-gray-700 transition-colors">描述</p>
</div>

<!-- peer: 兄弟元素状态响应 -->
<input type="checkbox" id="agree" class="peer hidden">
<label for="agree" class="cursor-pointer text-gray-500 peer-checked:text-blue-500">
  勾选后变蓝
</label>

6.2 暗色模式

v4 支持两种暗色模式策略:

css
@import "tailwindcss";

/* 方式 1:跟随系统设置(默认) */
@custom-variant dark (&:is(.dark *));

/* 方式 2:class 策略(手动切换) */
/* 在 <html> 上加 .dark 类即可 */
html
<!-- 使用 dark: 前缀 -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">
  <h1 class="text-2xl font-bold">自动适配暗色模式</h1>
  <p class="text-gray-600 dark:text-gray-400">切换系统主题看效果</p>
</div>

<!-- 完整暗色模式组件 -->
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 transition-colors">
  <h3 class="text-gray-900 dark:text-white font-bold text-lg mb-2">卡片标题</h3>
  <p class="text-gray-600 dark:text-gray-300 text-sm">卡片内容在暗色模式下自动适配</p>
  <button class="mt-4 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white px-4 py-2 rounded-lg transition-colors">
    操作按钮
  </button>
</div>

JavaScript 切换暗色模式:

javascript
// 暗色模式切换逻辑
function toggleDark() {
  document.documentElement.classList.toggle('dark')
}

// 读取本地存储
if (localStorage.theme === 'dark' || 
    (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
  document.documentElement.classList.add('dark')
} else {
  document.documentElement.classList.remove('dark')
}

6.3 过渡动画

html
<!-- 颜色过渡 -->
<button class="bg-blue-500 hover:bg-red-500 transition-colors duration-300">
  300ms 颜色过渡
</button>

<!-- 多属性过渡 -->
<div class="bg-white hover:bg-blue-500 text-gray-900 hover:text-white p-4 rounded-lg transition-all duration-500">
  500ms 全属性过渡
</div>

<!-- 变换过渡 -->
<div class="hover:scale-110 hover:rotate-3 transition-transform duration-300 cursor-pointer">
  悬停放大旋转
</div>

<!-- 延迟 -->
<div class="hover:translate-x-4 transition-transform duration-300 delay-150">
  延迟 150ms 后移动
</div>

过渡属性速查:

类名说明
transition-none无过渡
transition-all所有属性
transition-colorscolor/background/border
transition-opacityopacity
transition-transformtransform
transition-shadowbox-shadow
duration-150150ms
duration-300300ms
duration-500500ms
delay-150延迟 150ms
ease-in加速
ease-out减速
ease-in-out先加速后减速

6.4 自定义动画

css
@theme {
  --animate-fade-in: fade-in 0.5s ease-out;
  --animate-slide-up: slide-up 0.4s ease-out;
  --animate-bounce-slow: bounce-slow 2s ease-in-out infinite;
  --animate-spin-slow: spin 3s linear infinite;

  @keyframes fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
  }

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

  @keyframes bounce-slow {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-10px); }
  }
}
html
<!-- 使用自定义动画 -->
<div class="animate-fade-in">淡入</div>
<div class="animate-slide-up">从下方滑入</div>
<div class="animate-bounce-slow">缓慢弹跳</div>
<div class="animate-spin-slow">缓慢旋转</div>

七、实战项目

7.1 博客首页

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>技术博客</title>
  <link rel="stylesheet" href="/style.css">
</head>
<body class="bg-gray-50 text-gray-900 min-h-screen">
  
  <!-- 导航栏 -->
  <nav class="bg-white border-b border-gray-100 sticky top-0 z-50">
    <div class="max-w-4xl mx-auto px-4 h-16 flex items-center justify-between">
      <div class="flex items-center gap-2">
        <div class="w-8 h-8 bg-indigo-500 rounded-lg"></div>
        <span class="font-bold text-lg">DevBlog</span>
      </div>
      <div class="flex items-center gap-6 text-sm">
        <a href="#" class="text-gray-700 hover:text-indigo-500">文章</a>
        <a href="#" class="text-gray-700 hover:text-indigo-500">标签</a>
        <a href="#" class="text-gray-700 hover:text-indigo-500">关于</a>
      </div>
    </div>
  </nav>

  <!-- Hero -->
  <header class="max-w-4xl mx-auto px-4 py-16 text-center">
    <h1 class="text-4xl md:text-5xl font-bold tracking-tight">
      探索 <span class="text-indigo-500">前端技术</span> 的无限可能
    </h1>
    <p class="mt-4 text-lg text-gray-600 max-w-2xl mx-auto">
      分享 Vue、React、CSS、构建工具的实战经验与最佳实践
    </p>
    <div class="mt-8 flex justify-center gap-4">
      <button class="bg-indigo-500 hover:bg-indigo-600 text-white font-medium px-6 py-2.5 rounded-lg transition-colors">
        浏览文章
      </button>
      <button class="border border-gray-300 hover:border-indigo-500 hover:text-indigo-500 font-medium px-6 py-2.5 rounded-lg transition-colors">
        订阅 RSS
      </button>
    </div>
  </header>

  <!-- 文章列表 -->
  <main class="max-w-4xl mx-auto px-4 pb-16">
    <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
      <!-- 文章卡片 -->
      <article class="group bg-white rounded-xl shadow-sm hover:shadow-lg transition-all duration-300 overflow-hidden cursor-pointer">
        <div class="aspect-video bg-gradient-to-br from-indigo-400 to-purple-500"></div>
        <div class="p-6">
          <div class="flex items-center gap-2 mb-3">
            <span class="text-xs font-medium text-indigo-500 bg-indigo-50 px-2 py-1 rounded">Vue</span>
            <span class="text-xs text-gray-500">2026-07-11</span>
          </div>
          <h2 class="text-lg font-bold group-hover:text-indigo-500 transition-colors">
            Vue 3 Composition API 最佳实践
          </h2>
          <p class="mt-2 text-sm text-gray-600 leading-relaxed">
            深入理解 setup、ref、reactive、computed 和 watch 的使用场景...
          </p>
        </div>
      </article>

      <article class="group bg-white rounded-xl shadow-sm hover:shadow-lg transition-all duration-300 overflow-hidden cursor-pointer">
        <div class="aspect-video bg-gradient-to-br from-blue-400 to-teal-500"></div>
        <div class="p-6">
          <div class="flex items-center gap-2 mb-3">
            <span class="text-xs font-medium text-blue-500 bg-blue-50 px-2 py-1 rounded">CSS</span>
            <span class="text-xs text-gray-500">2026-07-10</span>
          </div>
          <h2 class="text-lg font-bold group-hover:text-indigo-500 transition-colors">
            Tailwind CSS v4 实战指南
          </h2>
          <p class="mt-2 text-sm text-gray-600 leading-relaxed">
            从零开始掌握 Tailwind v4 的 CSS-first 配置和组件构建...
          </p>
        </div>
      </article>
    </div>
  </main>

  <!-- 页脚 -->
  <footer class="border-t border-gray-100 bg-white">
    <div class="max-w-4xl mx-auto px-4 py-8 text-center text-sm text-gray-500">
      © 2026 DevBlog. Built with Vite + Tailwind CSS v4.
    </div>
  </footer>

</body>
</html>

7.2 仪表盘布局

html
<div class="min-h-screen bg-gray-50 flex">
  <!-- 侧边栏 -->
  <aside class="w-64 bg-gray-900 text-gray-300 hidden md:flex flex-col">
    <div class="p-6">
      <div class="flex items-center gap-2 text-white">
        <div class="w-8 h-8 bg-indigo-500 rounded-lg flex items-center justify-center font-bold">D</div>
        <span class="font-bold">Dashboard</span>
      </div>
    </div>
    <nav class="flex-1 px-3 space-y-1">
      <a href="#" class="flex items-center gap-3 px-3 py-2 rounded-lg bg-indigo-500 text-white text-sm">
        📊 概览
      </a>
      <a href="#" class="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-gray-800 text-sm">
        📈 分析
      </a>
      <a href="#" class="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-gray-800 text-sm">
        👥 用户
      </a>
      <a href="#" class="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-gray-800 text-sm">
        ⚙️ 设置
      </a>
    </nav>
  </aside>

  <!-- 主内容 -->
  <main class="flex-1 p-6">
    <!-- 统计卡片 -->
    <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
      <div class="bg-white rounded-xl shadow-sm p-6">
        <p class="text-sm text-gray-500">总用户</p>
        <p class="text-2xl font-bold text-gray-900 mt-1">12,847</p>
        <p class="text-xs text-green-500 mt-2">↑ 12.5% 较上月</p>
      </div>
      <div class="bg-white rounded-xl shadow-sm p-6">
        <p class="text-sm text-gray-500">活跃用户</p>
        <p class="text-2xl font-bold text-gray-900 mt-1">3,294</p>
        <p class="text-xs text-green-500 mt-2">↑ 8.2% 较上月</p>
      </div>
      <div class="bg-white rounded-xl shadow-sm p-6">
        <p class="text-sm text-gray-500">收入</p>
        <p class="text-2xl font-bold text-gray-900 mt-1">¥48,290</p>
        <p class="text-xs text-red-500 mt-2">↓ 3.1% 较上月</p>
      </div>
      <div class="bg-white rounded-xl shadow-sm p-6">
        <p class="text-sm text-gray-500">转化率</p>
        <p class="text-2xl font-bold text-gray-900 mt-1">3.47%</p>
        <p class="text-xs text-green-500 mt-2">↑ 0.8% 较上月</p>
      </div>
    </div>

    <!-- 表格 -->
    <div class="bg-white rounded-xl shadow-sm overflow-hidden">
      <div class="px-6 py-4 border-b border-gray-100">
        <h3 class="font-bold text-gray-900">最近订单</h3>
      </div>
      <table class="w-full">
        <thead class="bg-gray-50">
          <tr>
            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">订单号</th>
            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">客户</th>
            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">金额</th>
            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">状态</th>
          </tr>
        </thead>
        <tbody class="divide-y divide-gray-100">
          <tr class="hover:bg-gray-50">
            <td class="px-6 py-4 text-sm text-gray-900">#001</td>
            <td class="px-6 py-4 text-sm text-gray-600">张三</td>
            <td class="px-6 py-4 text-sm text-gray-900">¥299</td>
            <td class="px-6 py-4">
              <span class="px-2 py-1 text-xs font-medium text-green-700 bg-green-100 rounded-full">已完成</span>
            </td>
          </tr>
          <tr class="hover:bg-gray-50">
            <td class="px-6 py-4 text-sm text-gray-900">#002</td>
            <td class="px-6 py-4 text-sm text-gray-600">李四</td>
            <td class="px-6 py-4 text-sm text-gray-900">¥599</td>
            <td class="px-6 py-4">
              <span class="px-2 py-1 text-xs font-medium text-yellow-700 bg-yellow-100 rounded-full">处理中</span>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </main>
</div>

7.3 Landing Page

html
<div class="min-h-screen bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900 text-white">
  <!-- 导航 -->
  <nav class="fixed top-0 left-0 right-0 z-50 backdrop-blur-lg bg-slate-900/50 border-b border-white/10">
    <div class="max-w-6xl mx-auto px-4 h-16 flex items-center justify-between">
      <span class="font-bold text-lg">🚀 LaunchApp</span>
      <div class="flex items-center gap-6 text-sm">
        <a href="#" class="hover:text-purple-300 transition-colors">功能</a>
        <a href="#" class="hover:text-purple-300 transition-colors">价格</a>
        <a href="#" class="hover:text-purple-300 transition-colors">文档</a>
        <button class="bg-white text-slate-900 font-medium px-4 py-2 rounded-lg hover:bg-purple-100 transition-colors">
          免费试用
        </button>
      </div>
    </div>
  </nav>

  <!-- Hero -->
  <section class="pt-32 pb-20 px-4 text-center">
    <div class="max-w-3xl mx-auto">
      <span class="inline-block px-4 py-1.5 bg-purple-500/20 text-purple-300 text-sm rounded-full mb-6">
        ✨ 全新 v4.0 发布
      </span>
      <h1 class="text-5xl md:text-6xl font-bold tracking-tight">
        下一代<br>
        <span class="bg-gradient-to-r from-purple-400 to-pink-400 bg-clip-text text-transparent">
          开发者工具
        </span>
      </h1>
      <p class="mt-6 text-lg text-gray-300 max-w-xl mx-auto">
        从想法到上线,只需几分钟。极速构建、智能部署、实时监控,一站式解决。
      </p>
      <div class="mt-10 flex flex-col sm:flex-row justify-center gap-4">
        <button class="bg-purple-500 hover:bg-purple-600 text-white font-medium px-8 py-3 rounded-xl transition-all hover:scale-105">
          立即开始
        </button>
        <button class="border border-white/20 hover:bg-white/10 text-white font-medium px-8 py-3 rounded-xl transition-colors">
          查看演示
        </button>
      </div>
    </div>
  </section>

  <!-- 特性 -->
  <section class="py-20 px-4">
    <div class="max-w-5xl mx-auto grid grid-cols-1 md:grid-cols-3 gap-8">
      <div class="bg-white/5 backdrop-blur rounded-2xl p-8 border border-white/10 hover:border-purple-500/50 transition-colors">
        <div class="w-12 h-12 bg-purple-500/20 rounded-xl flex items-center justify-center text-2xl mb-4">⚡</div>
        <h3 class="text-xl font-bold mb-2">极速构建</h3>
        <p class="text-gray-400 text-sm">Rust 引擎驱动,构建速度提升 10 倍</p>
      </div>
      <div class="bg-white/5 backdrop-blur rounded-2xl p-8 border border-white/10 hover:border-purple-500/50 transition-colors">
        <div class="w-12 h-12 bg-pink-500/20 rounded-xl flex items-center justify-center text-2xl mb-4">🔒</div>
        <h3 class="text-xl font-bold mb-2">安全可靠</h3>
        <p class="text-gray-400 text-sm">端到端加密,SOC 2 合规认证</p>
      </div>
      <div class="bg-white/5 backdrop-blur rounded-2xl p-8 border border-white/10 hover:border-purple-500/50 transition-colors">
        <div class="w-12 h-12 bg-blue-500/20 rounded-xl flex items-center justify-center text-2xl mb-4">📊</div>
        <h3 class="text-xl font-bold mb-2">实时监控</h3>
        <p class="text-gray-400 text-sm">全链路可观测,异常秒级告警</p>
      </div>
    </div>
  </section>

  <!-- CTA -->
  <section class="py-20 px-4 text-center">
    <div class="max-w-2xl mx-auto bg-gradient-to-r from-purple-500/20 to-pink-500/20 rounded-3xl p-12 border border-white/10">
      <h2 class="text-3xl font-bold mb-4">准备好开始了吗?</h2>
      <p class="text-gray-300 mb-8">免费试用 14 天,无需信用卡</p>
      <button class="bg-white text-slate-900 font-bold px-8 py-3 rounded-xl hover:scale-105 transition-transform">
        创建账户
      </button>
    </div>
  </section>
</div>

八、性能优化

8.1 构建产物分析

v4 的 Oxide 引擎自动进行 Tree Shaking,只生成实际使用到的 CSS。

bash
# 构建项目
pnpm build

# 查看产物大小
ls -lh dist/assets/*.css
# 通常 10-30KB(gzip 后 3-8KB)

CSS 体积参考:

项目规模类名数量CSS 大小gzip 后
小型(10 页面)~2008-12 KB3-4 KB
中型(50 页面)~50015-20 KB5-7 KB
大型(100+ 页面)~100025-35 KB8-12 KB

8.2 优化策略

css
@import "tailwindcss";

/* 1. 按需导入核心模块(减少基础样式体积) */
@layer theme, base, components, utilities;

/* 2. 使用 @source 明确指定源文件范围 */
@source "../src/**/*.{vue,ts,tsx}";
@source "../content/**/*.md";

/* 3. 禁用不需要的前缀变体 */
@variant not-(*);

优化检查清单:

项目说明优先级
使用构建工具不要用 CDN 做生产环境🔴
检查 @source 范围避免扫描不必要的文件🟡
使用 @layer 分层控制样式优先级🟡
开启 gzip/brotli服务端压缩🔴
避免大量 @apply@apply 会增加 CSS 体积🟢
使用 @utility 注册自定义类替代 @layer components🟢

8.3 @apply 使用

@apply 在 v4 中仍然支持,但建议谨慎使用:

css
@import "tailwindcss";

/* ✅ 推荐:用于真正的可复用组件类 */
@utility btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  border-radius: 0.5rem;
  font-weight: 500;
  transition: all 0.15s;
}

@utility btn-primary {
  background-color: var(--color-blue-500);
  color: white;
}

@utility btn-primary:hover {
  background-color: var(--color-blue-600);
}

/* ⚠️ 谨慎使用 @apply */
.card {
  @apply bg-white rounded-xl shadow-sm p-6;
  /* 可以用,但会让 CSS 体积变大 */
}

8.4 与 VitePress 集成

本站就是 VitePress 项目,Tailwind v4 可以完美集成:

bash
# 安装
pnpm add tailwindcss @tailwindcss/vite

.vitepress/config.ts

typescript
import { defineConfig } from 'vitepress'
import tailwindcss from '@tailwindcss/vite'

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

.vitepress/theme/style.css

css
@import "tailwindcss";

/* VitePress 与 Tailwind 共存的注意事项 */
/* VitePress 的默认样式可能与 Tailwind 的 preflight 冲突 */
/* 可以禁用 preflight 或按需覆盖 */
@layer base {
  /* 保留 VitePress 的默认 body 样式 */
}

九、常用速查表

9.1 间距速查

前缀属性示例
p-paddingp-4 = 16px 内边距
m-marginm-4 = 16px 外边距
px-padding-left/rightpx-4
py-padding-top/bottompy-4
mx-margin-left/rightmx-auto 水平居中
my-margin-top/bottommy-4
pt/pr/pb/pl-单方向 paddingpt-2
mt/mr/mb/ml-单方向 marginmt-4
gap-flex/grid 间距gap-4
space-x-子元素水平间距space-x-4
space-y-子元素垂直间距space-y-4

9.2 Flex/Grid 速查

类名说明
flexdisplay: flex
inline-flexdisplay: inline-flex
griddisplay: grid
flex-row / flex-col主轴方向
justify-center/between/around/evenly主轴对齐
items-center/start/end/stretch交叉轴对齐
flex-1flex: 1 1 0%
flex-wrap换行
grid-cols-NN 列网格
col-span-N跨 N 列
gap-N间距

9.3 文字速查

类名说明示例值
text-xs12px0.75rem
text-sm14px0.875rem
text-base16px1rem
text-lg18px1.125rem
text-xl20px1.25rem
text-2xl24px1.5rem
font-light/normal/medium/bold300/400/500/700
text-left/center/right对齐
truncate单行省略
line-clamp-2/3多行省略

9.4 v4 新增工具类

类名说明
rotate-x-453D X 轴旋转
rotate-y-453D Y 轴旋转
perspective-10003D 透视
transform-3d启用 3D 变换
mask-*遮罩效果
text-shadow-*文字阴影
@container容器查询容器
@sm: / @md: / @lg:容器查询断点
inset-ring-*内嵌环形阴影
field-sizing-content表单字段自动高度

十、常见问题

Q1:类名太长怎么办?会不会影响可读性?

这是 Tailwind 最常见的质疑。解决方案:

  1. 组件化拆分:将重复的类名组合抽取为 Vue/React 组件
  2. @utility 自定义类:在 CSS 中注册可复用的工具类
  3. @apply 适度使用:对真正高频的组合可以用 @apply 提取
  4. clsx / tailwind-merge:动态拼接类名时使用工具库
vue
<!-- Vue 组件化 -->
<template>
  <BaseButton variant="primary" size="md">点击</BaseButton>
</template>
Q2:如何与传统 CSS 项目混用?

v4 可以和现有 CSS 共存。Tailwind 的 preflight(基础重置)可能影响现有样式,可以禁用:

css
@import "tailwindcss" source(none);

/* 手动导入需要的模块 */
@import "tailwindcss/utilities";
@import "tailwindcss/theme";
/* 不导入 tailwindcss/preflight 避免重置 */
Q3:Tailwind 有哪些推荐的组件库?
组件库框架说明
shadcn/uiReact最流行,基于 Radix UI
shadcn-vueVueshadcn/ui 的 Vue 移植
DaisyUI通用纯 CSS 组件类
Headless UIReact/VueTailwind 官方无样式组件
Park UIReact/Vue/Solid基于 Ark UI
Flowbite通用带 JS 交互的组件
Q4:v4 还需要 PostCSS 配置吗?

不需要。v4 使用原生 Vite 插件 @tailwindcss/vite,不再依赖 PostCSS。如果你用的是其他构建工具(Webpack、Rollup),可以使用 @tailwindcss/postcss 插件。但 Vite 用户直接用原生插件即可,性能更好。

Q5:如何在 Vue/React 中动态拼接类名?
vue
<!-- Vue -->
<template>
  <div :class="[
    'px-4 py-2 rounded-lg font-medium transition-colors',
    variant === 'primary' ? 'bg-blue-500 text-white hover:bg-blue-600' : '',
    variant === 'danger' ? 'bg-red-500 text-white hover:bg-red-600' : '',
    { 'opacity-50 cursor-not-allowed': disabled }
  ]">
    <slot />
  </div>
</template>
jsx
// React (推荐用 clsx + tailwind-merge)
import { clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'

function cn(...inputs) {
  return twMerge(clsx(inputs))
}

<button className={cn(
  'px-4 py-2 rounded-lg font-medium transition-colors',
  variant === 'primary' && 'bg-blue-500 text-white hover:bg-blue-600',
  variant === 'danger' && 'bg-red-500 text-white hover:bg-red-600',
  disabled && 'opacity-50 cursor-not-allowed'
)}>
  点击
</button>
Q6:Tailwind v4 支持 Sass/Less 吗?

可以共存,但不推荐混用。v4 的 @theme 和 CSS 变量已经替代了 Sass 的大部分功能(变量、嵌套、混入)。如果必须用 Sass,确保在 Tailwind 的 CSS 之前导入:

css
/* 先导入 Tailwind */
@import "tailwindcss";

/* 再写 Sass 生成的 CSS */
@import "./custom.scss";
Q7:如何调试找不到生成的 CSS 类?
  1. 确保类名拼写正确(用 VS Code IntelliSense 自动补全)
  2. 检查 @source 范围是否覆盖了你的文件
  3. 使用浏览器 DevTools 检查元素是否有对应样式
  4. 临时添加 @source inline("{类名}") 强制生成
  5. 查看 Tailwind 的构建日志
Q8:v4 的 @theme 和 v3 的 tailwind.config.js 有什么区别?
维度v3 config.jsv4 @theme
语言JavaScriptCSS
位置项目根目录CSS 入口文件
类型检查需要 JSDoc原生 CSS
热更新重启服务即时生效
扩展方式theme.extend@theme 嵌套
条件逻辑支持 JS 逻辑纯声明式

核心区别是:v4 认为 CSS 配置应该在 CSS 中,而不是 JS 中。这更符合关注点分离原则,也避免了 JS 配置文件的类型推断问题。


总结

Tailwind CSS v4 是一次架构级的进化——Rust 引擎带来了极致性能,CSS-first 配置简化了开发流程,内置容器查询和 3D 变换跟上现代 CSS 趋势。

核心要点回顾:

  1. 极简安装pnpm add tailwindcss @tailwindcss/vite + @import "tailwindcss",三步完成
  2. CSS-first 配置:用 @theme 替代 tailwind.config.js,所有设计 token 在 CSS 中定义
  3. 自动内容检测:不再需要配置 content 路径
  4. 容器查询内置:组件级响应式布局开箱即用
  5. 性能提升 10 倍:Rust 引擎 + Tree Shaking

延伸阅读:

🎯 Tailwind CSS v4 用更少的配置做更多的事。如果你还在犹豫,花 10 分钟搭建一个 Vite 项目试试——你会回不去的。