mcpField
T
tailwind-v4-shadcn

tailwind-v4-shadcn

github.com/jezweb设计与 UI1.1k2.6k 次安装3 周前更新
代码仓库

关于 tailwind-v4-shadcn

这是一份使用 Tailwind CSS v4 和 shadcn/ui 构建 React 应用的配置与故障排查指南,面向设置该技术栈的开发者。指南规定了基于 CSS 变量的主题架构,并说明常见迁移和样式错误的处理方法。

主要功能

  1. 01使用 Vite 配置 Tailwind CSS v4
  2. 02将 CSS 变量映射为 Tailwind 工具类
  3. 03设置浅色和深色主题
  4. 04排查常见配置与样式错误
  5. 05使用 v4 插件语法和内置功能

适用场景

  1. 01用 Tailwind CSS v4 和 shadcn/ui 创建 React 项目
  2. 02将项目从 Tailwind CSS v3 习惯迁移
  3. 03解决工具类颜色缺失或深色模式问题
  4. 04配置排版或表单插件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jezweb/claude-skills --skill tailwind-v4-shadcn

安装后在 Claude Code 中输入/tailwind-v4-shadcn确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
.claude-plugin/
plugin.json
commands/
setup.md
references/
architecture.md
common-gotchas.md
dark-mode.md
migration-guide.md
rules/
tailwind-v4-shadcn.md
templates/
components.json
index.css
theme-provider.tsx
tsconfig.app.json
utils.ts
vite.config.ts

详细介绍

Tailwind v4 + shadcn/ui 生产级技术栈

经过生产环境验证:WordPress Auditor (https://wordpress-auditor.webfonts.workers.dev) 最后更新:2026-01-20 版本:[email protected], @tailwindcss/[email protected] 状态:已可用于生产环境 ✅


快速开始(严格按此顺序操作)

# 1. Install dependencies
pnpm add tailwindcss @tailwindcss/vite
pnpm add -D @types/node tw-animate-css
pnpm dlx shadcn@latest init

# 2. Delete v3 config if exists
rm tailwind.config.ts  # v4 doesn't use this file

vite.config.ts:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
import path from 'path'

export default defineConfig({
  plugins: [react(), tailwindcss()],
  resolve: { alias: { '@': path.resolve(__dirname, './src') } }
})

components.json(至关重要):

{
  "tailwind": {
    "config": "",              // ← Empty for v4
    "css": "src/index.css",
    "baseColor": "slate",
    "cssVariables": true
  }
}

四步架构(必须遵循)

跳过步骤会导致主题失效。请严格遵循:

第 1 步:在根级别定义 CSS 变量
/* src/index.css */
@import "tailwindcss";
@import "tw-animate-css";  /* Required for shadcn/ui animations */

:root {
  --background: hsl(0 0% 100%);      /* ← hsl() wrapper required */
  --foreground: hsl(222.2 84% 4.9%);
  --primary: hsl(221.2 83.2% 53.3%);
  /* ... all light mode colors */
}

.dark {
  --background: hsl(222.2 84% 4.9%);
  --foreground: hsl(210 40% 98%);
  --primary: hsl(217.2 91.2% 59.8%);
  /* ... all dark mode colors */
}

至关重要:在根级别定义(不要放在 @layer base 内)。使用 hsl() 包装。

第 2 步:将变量映射到 Tailwind 工具类
@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-primary: var(--primary);
  /* ... map ALL CSS variables */
}

原因:生成工具类(bg-background、text-primary)。没有此映射,这些工具类就不会存在。

第 3 步:应用基础样式
@layer base {
  body {
    background-color: var(--background);  /* NO hsl() wrapper here */
    color: var(--foreground);
  }
}

至关重要:直接引用变量。切勿重复包装:hsl(var(--background))。

第 4 步:结果——自动暗色模式
<div className="bg-background text-foreground">
  {/* No dark: variants needed - theme switches automatically */}
</div>

暗色模式设置

1. 创建 ThemeProvider(参见 templates/theme-provider.tsx)

2. 包装 App:

// src/main.tsx
import { ThemeProvider } from '@/components/theme-provider'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
    <App />
  </ThemeProvider>
)

3. 添加主题切换按钮:

pnpm dlx shadcn@latest add dropdown-menu

ModeToggle 组件请参见 reference/dark-mode.md。


关键规则

✅ 务必执行:
  1. 在 :root/.dark 中使用 hsl() 包装颜色:--bg: hsl(0 0% 100%);
  2. 使用 @theme inline 映射所有 CSS 变量
  3. 在 components.json 中设置 "tailwind.config": ""
  4. 如果存在 tailwind.config.ts,请将其删除
  5. 使用 @tailwindcss/vite 插件(不要使用 PostCSS)
❌ 切勿执行:
  1. 将 :root/.dark 放在 @layer base 内(会导致层叠问题)
  2. 使用 .dark { @theme { } } 模式(v4 不支持嵌套的 @theme)
  3. 重复包装颜色:hsl(var(--background))
  4. 使用 tailwind.config.ts 配置主题(v4 会忽略它)
  5. 使用 @apply 指令(在 v4 中已弃用,参见错误 #7)
  6. 对语义颜色使用 dark: 变体(会自动处理)
  7. 对 @layer base 或 @layer components 中的类使用 @apply(v4 破坏性变更——改用 @utility) | 来源
  8. 未了解 CSS 层顺序就将任何样式放入 @layer base(参见错误 #8) | 来源

常见错误与解决方案

此技能可避免 8 个已记录的错误。

1. ❌ tw-animate-css 导入错误

错误:"Cannot find module 'tailwindcss-animate'"

原因:shadcn/ui 已弃用 tailwindcss-animate,不再用于 v4。

解决方案:

# ✅ DO
pnpm add -D tw-animate-css

# Add to src/index.css:
@import "tailwindcss";
@import "tw-animate-css";

# ❌ DON'T
npm install tailwindcss-animate  # v3 only

2. ❌ 颜色不生效

错误:bg-primary 未应用样式

原因:缺少 @theme inline 映射

解决方案:

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-primary: var(--primary);
  /* ... map ALL CSS variables */
}

3. ❌ 暗色模式未切换

错误:主题始终保持浅色/暗色

原因:缺少 ThemeProvider

解决方案:

  1. 创建 ThemeProvider(参见 templates/theme-provider.tsx)
  2. 在 main.tsx 中包装 app
  3. 确认 .dark 类会在 <html> 元素上切换

4. ❌ 重复的 @layer base

错误:控制台中出现 "Duplicate @layer base"

原因:shadcn init 会添加 @layer base——不要再添加一个

解决方案:

/* ✅ Correct - single @layer base */
@import "tailwindcss";

:root { --background: hsl(0 0% 100%); }

@theme inline { --color-background: var(--background); }

@layer base { body { background-color: var(--background); } }

5. ❌ 使用 tailwind.config.ts 导致构建失败

错误:"Unexpected config file"

原因:v4 不使用 tailwind.config.ts(v3 遗留配置)

解决方案:

rm tailwind.config.ts

v4 配置通过 @theme 指令在 src/index.css 中完成。


6. ❌ 多主题设置中,@theme inline 会破坏深色模式

错误:将 @theme inline 与自定义变体(例如 data-mode="dark")搭配使用时,深色模式无法切换
来源:GitHub 讨论 #18560

原因:@theme inline 会在构建时将变量的值嵌入工具类中。深色模式更改底层 CSS 变量时,工具类不会更新,因为它们引用的是硬编码的值,而不是变量。

发生原因:

  • @theme inline 会在构建时内联变量的值:bg-primary → background-color: oklch(...)
  • 深色模式覆盖会更改 CSS 变量,但工具类已经嵌入了变量的值
  • CSS 优先级链会中断

解决方案:在多主题场景中使用 @theme(不带 inline):

/* ✅ CORRECT - Use @theme without inline */
@custom-variant dark (&:where([data-mode=dark], [data-mode=dark] *));

@theme {
  --color-text-primary: var(--color-slate-900);
  --color-bg-primary: var(--color-white);
}

@layer theme {
  [data-mode="dark"] {
    --color-text-primary: var(--color-white);
    --color-bg-primary: var(--color-slate-900);
  }
}

适合使用 inline 的情况:

  • 单主题 + 深色模式切换(例如 shadcn/ui 默认配置)✅
  • 引用不会变化的其他 CSS 变量 ✅

不适合使用 inline 的情况:

  • 多主题系统(data-theme="blue" | "green" | 等)❌
  • 浅色/深色模式之外的动态主题切换 ❌

维护者建议(Adam Wathan):

“在 v4 中,让实际生成的 CSS 引用主题变量更符合惯用写法。就我个人而言,只有在不使用 inline 就无法正常工作的情况下才会使用它。”


7. ❌ @apply 与 @layer base/components 搭配使用(v4 重大变更)

错误:Cannot apply unknown utility class: custom-button
来源:GitHub 讨论 #17082

原因:在 v3 中,@layer base 和 @layer components 中定义的类可以与 @apply 搭配使用。在 v4 中,这是一个重大的架构变更。

发生原因:v4 不再“劫持”原生 CSS @layer at-rule。只有使用 @utility 定义的类才能用于 @apply。

迁移:

/* ❌ v3 pattern (worked) */
@layer components {
  .custom-button {
    @apply px-4 py-2 bg-blue-500;
  }
}

/* ✅ v4 pattern (required) */
@utility custom-button {
  @apply px-4 py-2 bg-blue-500;
}

/* OR use native CSS */
@layer base {
  .custom-button {
    padding: 1rem 0.5rem;
    background-color: theme(colors.blue.500);
  }
}

注意:本技能已建议尽量避免使用 @apply。此错误主要影响从 v3 迁移的用户。


8. ❌ @layer base 中定义的样式未生效

错误:似乎忽略了在 @layer base 中定义的样式
来源:GitHub 讨论 #16002 | 讨论 #18123

原因:v4 使用原生 CSS 层。如果没有明确指定层的顺序,受 CSS 层叠影响,基础样式可能会被工具类层覆盖。

发生原因:

  • v3:Tailwind 会拦截 @layer base/components/utilities 并进行特殊处理
  • v4:使用原生 CSS 层——如果未按正确顺序导入各层,优先级就会出问题
  • 样式确实已生效,但会被工具类覆盖

解决方案 1:明确指定层:

@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/base.css" layer(base);
@import "tailwindcss/components.css" layer(components);
@import "tailwindcss/utilities.css" layer(utilities);

@layer base {
  body {
    background-color: var(--background);
  }
}

解决方案 2(推荐):不要使用 @layer base——在根级别定义样式:

@import "tailwindcss";

:root {
  --background: hsl(0 0% 100%);
}

body {
  background-color: var(--background); /* No @layer needed */
}

适用范围:所有基础样式,而不仅仅是颜色变量。除非了解 CSS 层的顺序,否则应避免将任何样式放在 @layer base 中。


快速参考

症状原因修复方法
bg-primary 不起作用缺少 @theme inline添加 @theme inline 块
颜色全变成黑色/白色重复使用 hsl() 包裹使用 var(--color),而不是 hsl(var(--color))
深色模式无法切换缺少 ThemeProvider使用 <ThemeProvider> 包裹应用
构建失败存在 tailwind.config.ts删除该文件
动画报错使用了 tailwindcss-animate安装 tw-animate-css

Tailwind v4 的新内容

OKLCH 色彩空间(2024 年 12 月)

Tailwind v4.0 将整个默认调色板替换为 OKLCH,这是一种感知均匀的色彩空间。 来源:Tailwind v4.0 发布说明 | OKLCH 迁移指南

为何使用 OKLCH:

  • 感知一致性:HSL 的“50% 亮度”在不同色相间的视觉效果并不一致(相同亮度下,黄色看起来比蓝色亮得多)
  • 更好的渐变:平滑过渡,不会出现浑浊的中间色
  • 更宽的色域:在现代显示器上支持超出 sRGB 的颜色
  • 更鲜艳的颜色:醒目、饱和的颜色不再受 sRGB 限制

浏览器支持(2026 年 1 月):

  • Chrome 111+、Firefox 113+、Safari 15.4+、Edge 111+
  • 全球覆盖率:93.1%

自动回退:Tailwind 会为较旧的浏览器生成 sRGB 回退:

.bg-blue-500 {
  background-color: #3b82f6; /* sRGB fallback */
  background-color: oklch(0.6 0.24 264); /* Modern browsers */
}

自定义颜色:定义自定义颜色时,现在优先使用 OKLCH:

@theme {
  /* Modern approach (preferred) */
  --color-brand: oklch(0.7 0.15 250);

  /* Legacy approach (still works) */
  --color-brand: hsl(240 80% 60%);
}

迁移:没有破坏性变更——Tailwind 会自动生成回退。对于新项目,请使用支持 OKLCH 的工具来定义自定义颜色。

内置功能(无需插件)

容器查询(自 v4.0 起内置):

<div className="@container">
  <div className="@md:text-lg @lg:grid-cols-2">
    Content responds to container width, not viewport
  </div>
</div>

行数截断(自 v3.3 起内置):

<p className="line-clamp-3">Truncate to 3 lines with ellipsis...</p>
<p className="line-clamp-[8]">Arbitrary values supported</p>
<p className="line-clamp-(--teaser-lines)">CSS variable support</p>

已移除的插件:

  • @tailwindcss/container-queries - 现已内置
  • @tailwindcss/line-clamp - 自 v3.3 起已内置

Tailwind v4 插件

使用 @plugin 指令(不要使用 require() 或 @import):

排版(用于 Markdown/CMS 内容):

pnpm add -D @tailwindcss/typography
@import "tailwindcss";
@plugin "@tailwindcss/typography";
<article class="prose dark:prose-invert">{{ content }}</article>

表单(跨浏览器表单样式):

pnpm add -D @tailwindcss/forms
@import "tailwindcss";
@plugin "@tailwindcss/forms";

容器查询(内置,无需插件):

<div className="@container">
  <div className="@md:text-lg">Responds to container width</div>
</div>

常见插件错误:

/* ❌ WRONG - v3 syntax */
@import "@tailwindcss/typography";

/* ✅ CORRECT - v4 syntax */
@plugin "@tailwindcss/typography";

设置检查清单

  • 已安装 @tailwindcss/vite(不要安装 postcss)
  • vite.config.ts 使用 tailwindcss() 插件
  • components.json 中包含 "config": ""
  • 不存在 tailwind.config.ts
  • src/index.css 遵循 4 步模式:
    • :root/.dark 位于根级别(不在 @layer 中)
    • 颜色使用 hsl() 包裹
    • @theme inline 映射所有变量
    • @layer base 使用未包裹的变量
  • ThemeProvider 包裹应用
  • 主题切换功能正常

文件模板

位于 templates/ 目录中:

  • index.css - 包含所有颜色变量的完整 CSS
  • components.json - shadcn/ui v4 配置
  • vite.config.ts - Vite + Tailwind 插件
  • theme-provider.tsx - 深色模式提供程序
  • utils.ts - cn() 工具函数

从 v3 迁移

完整指南请参阅 reference/migration-guide.md。

主要变更:

  • 删除 tailwind.config.ts
  • 将主题移至 CSS,并使用 @theme inline
  • 替换 @tailwindcss/line-clamp(现已内置:line-clamp-*)
  • 用 tw-animate-css 替换 tailwindcss-animate
  • 更新插件:require() → @plugin
其他迁移注意事项
自动迁移工具可能会失败

警告:@tailwindcss/upgrade 工具通常无法迁移配置。 来源:社区报告 | GitHub 讨论 #16642

常见失败情况:

  • 排版插件配置
  • 复杂的主题扩展
  • 自定义插件设置

建议:不要依赖自动迁移。请改为按照迁移指南中的手动步骤操作。

已移除默认元素样式

Tailwind v4 采用了更精简的 Preflight 方案,移除了标题、列表和按钮的默认样式。 来源:GitHub Discussion #16517 | Medium:迁移问题

影响:

  • 所有标题(<h1> 到 <h6>)的渲染字号相同
  • 列表失去默认内边距
  • 现有项目出现视觉回归

解决方案:

选项 1:在内容页面中使用 @tailwindcss/typography:

pnpm add -D @tailwindcss/typography
@import "tailwindcss";
@plugin "@tailwindcss/typography";
<article className="prose dark:prose-invert">
  {/* All elements styled automatically */}
</article>

选项 2:添加自定义基础样式:

@layer base {
  h1 { @apply text-4xl font-bold mb-4; }
  h2 { @apply text-3xl font-bold mb-3; }
  h3 { @apply text-2xl font-bold mb-2; }
  ul { @apply list-disc pl-6 mb-4; }
  ol { @apply list-decimal pl-6 mb-4; }
}
PostCSS 设置复杂

建议:对于 Vite 项目,请使用 @tailwindcss/vite 插件,而不是 PostCSS。 来源:Medium:迁移问题 | GitHub Discussion #15764

Vite 插件更好的原因:

// ✅ Vite Plugin - One line, no PostCSS config
import tailwindcss from '@tailwindcss/vite'

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

// ❌ PostCSS - Multiple steps, plugin compatibility issues
// 1. Install @tailwindcss/postcss
// 2. Configure postcss.config.js
// 3. Manage plugin order
// 4. Debug plugin conflicts

报告的 PostCSS 问题:

  • 错误:“看起来你正尝试将 tailwindcss 直接用作 PostCSS 插件”
  • 需要多个 PostCSS 插件:postcss-import、postcss-advanced-variables、tailwindcss/nesting
  • v4 PostCSS 插件是独立包:@tailwindcss/postcss

官方指南:对于 Vite 项目,建议使用 Vite 插件。PostCSS 适用于旧版配置或非 Vite 环境。

视觉变化

Ring 默认宽度:从 3px 改为 1px 来源:Medium:迁移指南

  • ring 类现在更细
  • 使用 ring-3 以匹配 v3 的外观
// v3: 3px ring
<button className="ring">Button</button>

// v4: 1px ring (thinner)
<button className="ring">Button</button>

// Match v3 appearance
<button className="ring-3">Button</button>

参考文档

  • architecture.md - 深入了解 4 步模式
  • dark-mode.md - 完整的深色模式实现
  • common-gotchas.md - 故障排除指南
  • migration-guide.md - v3 → v4 迁移

官方文档


最后更新:2026-01-20 技能版本:3.0.0 Tailwind v4:4.1.18(最新) 生产环境:WordPress Auditor (https://wordpress-auditor.webfonts.workers.dev)

变更日志:

  • v3.0.0 (2026-01-20):重大研究更新——新增 3 个 TIER 1 错误(#6-8),根据社区发现扩展迁移指南(TIER 2),新增 OKLCH 色彩空间章节、PostCSS 复杂性警告和迁移工具限制
  • v2.0.1 (2026-01-03):生产环境验证
  • v2.0.0:首次发布,记录了 5 个错误

评论

支持 Markdown