Tailwind CSS v4 × Nuxt4 深度集成

Tailwind CSS v4 是一次架构级重写——从 JavaScript 配置迁移到 CSS-first 配置,构建速度提升 10 倍,并且原生支持 CSS 变量作为 Design Token。在 Nuxt4 生态中,@nuxtjs/tailwindcss 模块和 @nuxt/ui 组件库都已全面拥抱 v4。本章从 v4 的架构变革讲起,深入 CSS-first 配置、Nuxt UI 主题定制、Design Token 体系,最终落地一套完整的设计系统。

1. Tailwind v4 的架构变革

1.1 从 JS 配置到 CSS 配置

Tailwind v3 的配置写在 tailwind.config.js(JavaScript)中。v4 彻底改变了这个模式——配置写在 CSS 文件中

/* v3:tailwind.config.js */
/* module.exports = { theme: { colors: { primary: '#3b82f6' } } } */
 
/* v4:app.css */
@import "tailwindcss";
 
@theme {
  --color-primary: #3b82f6;
  --font-family-sans: 'Inter', sans-serif;
  --breakpoint-sm: 640px;
}

这个变化不是简单的语法迁移,而是架构哲学的转变

  • 零 JavaScript:配置不再需要 Node.js 解析,纯 CSS 引擎处理
  • CSS 变量原生@theme 中的值自动生成 CSS 变量(var(--color-primary)
  • 构建速度:新引擎用 Rust(Oxide)编写,全量构建 < 100ms,增量构建 < 10ms
  • 更小的输出:智能检测消除未使用的样式,产物更精简

1.2 Nuxt4 集成

npx nuxi module add @nuxtjs/tailwindcss
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/tailwindcss'],
  tailwindcss: {
    cssPath: '~/assets/css/tailwind.css',
  },
})
/* assets/css/tailwind.css */
@import "tailwindcss";
 
@theme {
  --color-primary: #3b82f6;
  --color-secondary: #6366f1;
}

@nuxtjs/tailwindcss 模块自动处理:

  • 自动扫描 components/pages/layouts/ 中的类名
  • HMR 热更新(修改 CSS 主题即时生效)
  • 与 Nuxt DevTools 集成

2. @theme:CSS-first 配置详解

2.1 颜色系统

@theme {
  /* 品牌色 */
  --color-primary: #3b82f6;
  --color-primary-50: #eff6ff;
  --color-primary-100: #dbeafe;
  --color-primary-500: #3b82f6;
  --color-primary-900: #1e3a5f;
 
  /* 语义色 */
  --color-success: #22c55e;
  --color-warning: #f59e0b;
  --color-error: #ef4444;
  --color-info: #06b6d4;
 
  /* 中性色 */
  --color-gray-50: #f9fafb;
  --color-gray-900: #111827;
}

@theme 中定义的颜色会自动生成工具类:bg-primarytext-primary-500border-error。同时生成 CSS 变量,可以在自定义 CSS 中通过 var(--color-primary) 引用。

2.2 排版系统

@theme {
  --font-family-sans: 'Inter', 'Noto Sans SC', sans-serif;
  --font-family-mono: 'JetBrains Mono', monospace;
 
  --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;
 
  --line-height-tight: 1.25;
  --line-height-normal: 1.5;
  --line-height-relaxed: 1.75;
}

2.3 间距与圆角

@theme {
  --spacing-0: 0;
  --spacing-1: 0.25rem;
  --spacing-2: 0.5rem;
  --spacing-4: 1rem;
  --spacing-8: 2rem;
 
  --radius-sm: 0.25rem;
  --radius-md: 0.375rem;
  --radius-lg: 0.5rem;
  --radius-xl: 0.75rem;
  --radius-full: 9999px;
}

2.4 动画

@theme {
  --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 { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

使用:&lt;div class="animate-fade-in"&gt;

3. Nuxt UI 主题定制

3.1 Nuxt UI 与 Tailwind v4

Nuxt UI v3 基于 Tailwind v4 和 Radix Vue 构建,提供 50+ 高质量组件。它的主题系统完全基于 CSS 变量:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxt/ui'],
  ui: {
    theme: {
      colors: ['primary', 'secondary', 'success', 'warning', 'error'],
    },
  },
})

3.2 组件级主题覆盖

Nuxt UI 的每个组件都有默认的样式变体,可以在 app.config.ts 中全局覆盖:

// app.config.ts
export default defineAppConfig({
  ui: {
    button: {
      defaultVariants: {
        size: 'md',
        color: 'primary',
      },
      slots: {
        base: 'rounded-lg font-medium transition-colors',
      },
    },
    input: {
      slots: {
        root: 'relative',
        base: 'rounded-lg border-gray-300 focus:border-primary focus:ring-primary',
      },
    },
  },
})

app.config.ts 中的覆盖是全局生效的——所有 &lt;UButton&gt; 组件都会使用你定义的样式。单个组件实例仍然可以通过 ui prop 局部覆盖。

3.3 组件实例覆盖

<template>
  <UButton
    :ui="{
      base: 'rounded-full px-8',
    }"
  >
    特殊按钮
  </UButton>
</template>

优先级:组件 ui prop > app.config.ts 全局配置 > Nuxt UI 默认样式。

4. Design Token 体系

4.1 什么是 Design Token

Design Token 是设计系统中可复用的最小设计决策单元——颜色、字号、间距、圆角、阴影等。它是设计师和开发者之间的契约

设计师在 Figma 中定义:Primary Color = #3b82f6
    ↓
导出为 Design Token(JSON / CSS 变量)
    ↓
开发者在代码中使用:bg-primary / var(--color-primary)

4.2 三层 Token 架构

成熟的设计系统通常有三层 Token:

层级命名示例含义示例值
Global--blue-500原始色板值#3b82f6
Alias--color-primary语义化引用var(--blue-500)
Component--button-bg组件级 Tokenvar(--color-primary)
/* 第一层:原始值 */
@theme {
  --blue-50: #eff6ff;
  --blue-500: #3b82f6;
  --blue-900: #1e3a5f;
}
 
/* 第二层:语义化别名 */
:root {
  --color-primary: var(--blue-500);
  --color-bg: var(--white);
  --color-text: var(--gray-900);
}
 
/* 第三层:组件级(暗黑模式自动切换) */
.dark {
  --color-primary: var(--blue-400);
  --color-bg: var(--gray-950);
  --color-text: var(--gray-100);
}

三层架构的好处:更换品牌色时只需修改 Alias 层(--color-primary),不需要改动组件代码。

4.3 与 Figma 同步

设计师在 Figma 中定义 Token,通过工具自动同步到代码:

工具方式特点
Figma TokensFigma 插件 + GitHub 同步最流行
Style DictionaryJSON → 多平台代码Amazon 开源
Panda CSS内置 Token 系统类型安全

工作流:设计师修改 Figma Token → 自动生成 PR 更新 CSS 变量 → 代码审核合并。

5. 实用模式

5.1 响应式设计

Tailwind v4 的断点定义:

@theme {
  --breakpoint-sm: 640px;
  --breakpoint-md: 768px;
  --breakpoint-lg: 1024px;
  --breakpoint-xl: 1280px;
  --breakpoint-2xl: 1536px;
}
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  <VideoCard v-for="video in videos" :key="video.id" :video="video" />
</div>

5.2 容器查询

Tailwind v4 原生支持容器查询——根据父容器而非视口宽度调整样式:

<div class="@container">
  <div class="@sm:flex @sm:items-center">
    <!-- 当父容器 >= 640px 时变为 flex 布局 -->
  </div>
</div>

容器查询在组件化开发中比媒体查询更实用——同一个卡片组件在侧边栏(窄)和主内容区(宽)自动适配。

5.3 自定义工具类

@utility content-auto {
  content-visibility: auto;
}
 
@utility scrollbar-hide {
  scrollbar-width: none;
  &::-webkit-scrollbar {
    display: none;
  }
}

使用:&lt;div class="content-auto scrollbar-hide"&gt;

5.4 避免常见陷阱

动态类名不生效

<!-- ❌ 动态拼接类名,Tailwind 无法检测 -->
<div :class="`bg-${color}-500`">
 
<!-- ✅ 使用完整类名映射 -->
<div :class="colorMap[color]">
 
<script setup>
const colorMap = {
  primary: 'bg-primary-500',
  success: 'bg-success-500',
  error: 'bg-error-500',
}
</script>

Tailwind 的 JIT 引擎通过静态分析源代码来检测类名,动态拼接的字符串无法被检测到。

本章小结

  • Tailwind v4 = CSS-first@theme 替代 tailwind.config.js,构建速度提升 10 倍,原生 CSS 变量
  • Nuxt 集成@nuxtjs/tailwindcss 自动扫描 + HMR,@nuxt/ui 基于 v4 提供 50+ 组件
  • 主题定制三层@theme 定义 Token → app.config.ts 全局覆盖 → 组件 ui prop 局部覆盖
  • Design Token 三层架构:Global(原始值)→ Alias(语义化)→ Component(组件级),便于品牌切换
  • 实用模式:容器查询替代媒体查询、@utility 自定义工具类、避免动态类名拼接