tailwind-v4-shadcn
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTailwind v4 + shadcn/ui Production Stack
Tailwind v4 + shadcn/ui 生产环境搭建方案
Production-tested: WordPress Auditor (https://wordpress-auditor.webfonts.workers.dev)
Last Updated: 2026-01-20
Versions: tailwindcss@4.1.18, @tailwindcss/vite@4.1.18
Status: Production Ready ✅
经生产环境验证:WordPress Auditor(https://wordpress-auditor.webfonts.workers.dev)
最后更新:2026-01-20
版本信息:tailwindcss@4.1.18, @tailwindcss/vite@4.1.18
状态:可用于生产环境 ✅
Quick Start (Follow This Exact Order)
快速开始(严格按照以下步骤执行)
bash
undefinedbash
undefined1. Install dependencies
1. 安装依赖
pnpm add tailwindcss @tailwindcss/vite
pnpm add -D @types/node tw-animate-css
pnpm dlx shadcn@latest init
pnpm add tailwindcss @tailwindcss/vite
pnpm add -D @types/node tw-animate-css
pnpm dlx shadcn@latest init
2. Delete v3 config if exists
2. 如果存在v3配置文件则删除
rm tailwind.config.ts # v4 doesn't use this file
**vite.config.ts**:
```typescript
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 (CRITICAL):
json
{
"tailwind": {
"config": "", // ← Empty for v4
"css": "src/index.css",
"baseColor": "slate",
"cssVariables": true
}
}rm tailwind.config.ts # v4 不使用该文件
**vite.config.ts**:
```typescript
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(至关重要):
json
{
"tailwind": {
"config": "", // ← v4 此处留空
"css": "src/index.css",
"baseColor": "slate",
"cssVariables": true
}
}The Four-Step Architecture (MANDATORY)
四步架构模式(必须严格执行)
Skipping steps will break your theme. Follow exactly:
跳过任何步骤都会导致主题失效,请严格遵循:
Step 1: Define CSS Variables at Root
步骤1:在根节点定义CSS变量
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 */
}Critical: Define at root level (NOT inside ). Use wrapper.
@layer basehsl()css
/* src/index.css */
@import "tailwindcss";
@import "tw-animate-css"; /* shadcn/ui 动画必需 */
:root {
--background: hsl(0 0% 100%); /* ← 必须使用hsl()包裹 */
--foreground: hsl(222.2 84% 4.9%);
--primary: hsl(221.2 83.2% 53.3%);
/* ... 所有浅色模式颜色 */
}
.dark {
--background: hsl(222.2 84% 4.9%);
--foreground: hsl(210 40% 98%);
--primary: hsl(217.2 91.2% 59.8%);
/* ... 所有深色模式颜色 */
}关键注意事项:在根级别定义(不要放在内部),使用包裹颜色值。
@layer basehsl()Step 2: Map Variables to Tailwind Utilities
步骤2:将变量映射到Tailwind工具类
css
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
/* ... map ALL CSS variables */
}Why: Generates utility classes (, ). Without this, utilities won't exist.
bg-backgroundtext-primarycss
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
/* ... 映射所有CSS变量 */
}作用:生成工具类(如、)。缺少此步骤,工具类将无法生效。
bg-backgroundtext-primaryStep 3: Apply Base Styles
步骤3:应用基础样式
css
@layer base {
body {
background-color: var(--background); /* NO hsl() wrapper here */
color: var(--foreground);
}
}Critical: Reference variables directly. Never double-wrap: .
hsl(var(--background))css
@layer base {
body {
background-color: var(--background); /* 此处不要使用hsl()包裹 */
color: var(--foreground);
}
}关键注意事项:直接引用变量,切勿双重包裹:。
hsl(var(--background))Step 4: Result - Automatic Dark Mode
步骤4:实现效果 - 自动深色模式
tsx
<div className="bg-background text-foreground">
{/* No dark: variants needed - theme switches automatically */}
</div>tsx
<div className="bg-background text-foreground">
{/* 无需使用dark:前缀 - 主题会自动切换 */}
</div>Dark Mode Setup
深色模式设置
1. Create ThemeProvider (see )
templates/theme-provider.tsx2. Wrap App:
typescript
// 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. Add Theme Toggle:
bash
pnpm dlx shadcn@latest add dropdown-menuSee for ModeToggle component.
reference/dark-mode.md1. 创建ThemeProvider(参考)
templates/theme-provider.tsx2. 包裹应用:
typescript
// 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. 添加主题切换按钮:
bash
pnpm dlx shadcn@latest add dropdown-menu参考获取ModeToggle组件代码。
reference/dark-mode.mdCritical Rules
关键规则
✅ Always Do:
✅ 必须执行:
- Wrap colors with in
hsl()/:root:.dark--bg: hsl(0 0% 100%); - Use to map all CSS variables
@theme inline - Set in components.json
"tailwind.config": "" - Delete if exists
tailwind.config.ts - Use plugin (NOT PostCSS)
@tailwindcss/vite
- 在/
:root中使用.dark包裹颜色:hsl()--bg: hsl(0 0% 100%); - 使用映射所有CSS变量
@theme inline - 在components.json中设置
"tailwind.config": "" - 如果存在则删除
tailwind.config.ts - 使用插件(不要使用PostCSS)
@tailwindcss/vite
❌ Never Do:
❌ 禁止操作:
- Put /
:rootinside.dark(causes cascade issues)@layer base - Use pattern (v4 doesn't support nested @theme)
.dark { @theme { } } - Double-wrap colors:
hsl(var(--background)) - Use for theme (v4 ignores it)
tailwind.config.ts - Use directive (deprecated in v4, see error #7)
@apply - Use variants for semantic colors (auto-handled)
dark: - Use with
@applyor@layer baseclasses (v4 breaking change - use@layer componentsinstead) | Source@utility - Wrap ANY styles in without understanding CSS layer ordering (see error #8) | Source
@layer base
- 将/
:root放在.dark内部(会导致样式层级问题)@layer base - 使用模式(v4不支持嵌套的@theme)
.dark { @theme { } } - 双重包裹颜色:
hsl(var(--background)) - 使用配置主题(v4会忽略该文件)
tailwind.config.ts - 使用指令(v4中已废弃,参考错误#7)
@apply - 为语义化颜色使用前缀(已自动处理)
dark: - 在或
@layer base类中使用@layer components(v4破坏性变更 - 使用@apply替代) | 来源@utility - 在不了解CSS层级顺序的情况下,将任何样式包裹在中(参考错误#8) | 来源
@layer base
Common Errors & Solutions
常见错误与解决方案
This skill prevents 8 documented errors.
本方案可避免8种已记录的错误。
1. ❌ tw-animate-css Import Error
1. ❌ tw-animate-css 导入错误
Error: "Cannot find module 'tailwindcss-animate'"
Cause: shadcn/ui deprecated for v4.
tailwindcss-animateSolution:
bash
undefined错误信息:"Cannot find module 'tailwindcss-animate'"
原因:shadcn/ui在v4版本中废弃了。
tailwindcss-animate解决方案:
bash
undefined✅ DO
✅ 正确做法
pnpm add -D tw-animate-css
pnpm add -D tw-animate-css
Add to src/index.css:
在src/index.css中添加:
@import "tailwindcss";
@import "tw-animate-css";
@import "tailwindcss";
@import "tw-animate-css";
❌ DON'T
❌ 错误做法
npm install tailwindcss-animate # v3 only
---npm install tailwindcss-animate # 仅适用于v3
---2. ❌ Colors Not Working
2. ❌ 颜色不生效
Error: doesn't apply styles
bg-primaryCause: Missing mapping
@theme inlineSolution:
css
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
/* ... map ALL CSS variables */
}错误信息:样式未应用
bg-primary原因:缺少映射
@theme inline解决方案:
css
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
/* ... 映射所有CSS变量 */
}3. ❌ Dark Mode Not Switching
3. ❌ 深色模式无法切换
Error: Theme stays light/dark
Cause: Missing ThemeProvider
Solution:
- Create ThemeProvider (see )
templates/theme-provider.tsx - Wrap app in
main.tsx - Verify class toggles on
.darkelement<html>
错误信息:主题始终保持浅色/深色
原因:缺少ThemeProvider
解决方案:
- 创建ThemeProvider(参考)
templates/theme-provider.tsx - 在main.tsx中包裹应用
- 验证元素上的
<html>类是否正确切换.dark
4. ❌ Duplicate @layer base
4. ❌ 重复的@layer base
Error: "Duplicate @layer base" in console
Cause: shadcn init adds - don't add another
@layer baseSolution:
css
/* ✅ 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); } }错误信息:控制台出现"Duplicate @layer base"
原因:shadcn初始化时已添加 - 请勿重复添加
@layer base解决方案:
css
/* ✅ 正确写法 - 单个@layer base */
@import "tailwindcss";
:root { --background: hsl(0 0% 100%); }
@theme inline { --color-background: var(--background); }
@layer base { body { background-color: var(--background); } }5. ❌ Build Fails with tailwind.config.ts
5. ❌ 存在tailwind.config.ts导致构建失败
Error: "Unexpected config file"
Cause: v4 doesn't use (v3 legacy)
tailwind.config.tsSolution:
bash
rm tailwind.config.tsv4 configuration happens in using directive.
src/index.css@theme错误信息:"Unexpected config file"
原因:v4不使用(v3遗留文件)
tailwind.config.ts解决方案:
bash
rm tailwind.config.tsv4的配置通过中的指令完成。
src/index.css@theme6. ❌ @theme inline Breaks Dark Mode in Multi-Theme Setups
6. ❌ @theme inline 在多主题设置中破坏深色模式
Error: Dark mode doesn't switch when using with custom variants (e.g., )
Source: GitHub Discussion #18560
@theme inlinedata-mode="dark"Cause: bakes variable VALUES into utilities at build time. When dark mode changes the underlying CSS variables, utilities don't update because they reference hardcoded values, not variables.
@theme inlineWhy It Happens:
- inlines VALUES at build time:
@theme inline→bg-primarybackground-color: oklch(...) - Dark mode overrides change the CSS variables, but utilities already have baked-in values
- The CSS specificity chain breaks
Solution: Use (without inline) for multi-theme scenarios:
@themecss
/* ✅ 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);
}
}When to use inline:
- Single theme + dark mode toggle (like shadcn/ui default) ✅
- Referencing other CSS variables that don't change ✅
When NOT to use inline:
- Multi-theme systems (data-theme="blue" | "green" | etc.) ❌
- Dynamic theme switching beyond light/dark ❌
Maintainer Guidance (Adam Wathan):
"It's more idiomatic in v4 for the actual generated CSS to reference your theme variables. I would personally only use inline when things don't work without it."
原因:在构建时将变量值硬编码到工具类中。当深色模式修改底层CSS变量时,工具类不会更新,因为它们引用的是硬编码值而非变量。
@theme inline具体原因:
- 在构建时内联值:
@theme inline→bg-primarybackground-color: oklch(...) - 深色模式覆盖修改CSS变量,但工具类已包含硬编码值
- CSS优先级链断裂
解决方案:在多主题场景下使用不带inline的:
@themecss
/* ✅ 正确写法 - 使用不带inline的@theme */
@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 with @layer base/components (v4 Breaking Change)
7. ❌ 在@layer base/components中使用@apply(v4破坏性变更)
Error:
Source: GitHub Discussion #17082
Cannot apply unknown utility class: custom-buttonCause: In v3, classes defined in and could be used with . In v4, this is a breaking architectural change.
@layer base@layer components@applyWhy It Happens: v4 doesn't "hijack" the native CSS at-rule anymore. Only classes defined with are available to .
@layer@utility@applyMigration:
css
/* ❌ 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);
}
}Note: This skill already discourages usage. This error is primarily for users migrating from v3.
@apply错误信息:
来源:GitHub讨论 #17082
Cannot apply unknown utility class: custom-button原因:在v3中,和中定义的类可以与一起使用。在v4中,这是一个破坏性的架构变更。
@layer base@layer components@apply具体原因:v4不再劫持原生CSS的规则。只有使用定义的类才能用于。
@layer@utility@apply迁移方案:
css
/* ❌ v3写法(曾生效) */
@layer components {
.custom-button {
@apply px-4 py-2 bg-blue-500;
}
}
/* ✅ v4写法(必需) */
@utility custom-button {
@apply px-4 py-2 bg-blue-500;
}
/* 或使用原生CSS */
@layer base {
.custom-button {
padding: 1rem 0.5rem;
background-color: theme(colors.blue.500);
}
}注意:本方案已不推荐使用。此错误主要针对从v3迁移的用户。
@apply8. ❌ @layer base Styles Not Applying
8. ❌ @layer base 样式未生效
Error: Styles defined in seem to be ignored
Source: GitHub Discussion #16002 | Discussion #18123
@layer baseCause: v4 uses native CSS layers. Base styles CAN be overridden by utility layers due to CSS cascade if layers aren't explicitly ordered.
Why It Happens:
- v3: Tailwind intercepted and processed them specially
@layer base/components/utilities - v4: Uses native CSS layers - if you don't import layers in the right order, precedence breaks
- Styles ARE being applied, but utilities override them
Solution Option 1: Define layers explicitly:
css
@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);
}
}Solution Option 2 (Recommended): Don't use - define styles at root level:
@layer basecss
@import "tailwindcss";
:root {
--background: hsl(0 0% 100%);
}
body {
background-color: var(--background); /* No @layer needed */
}Applies to: ALL base styles, not just color variables. Avoid wrapping ANY styles in unless you understand CSS layer ordering.
@layer base原因:v4使用原生CSS层级。如果未显式指定层级顺序,基础样式可能会被工具类层级覆盖。
具体原因:
- v3:Tailwind会拦截并进行特殊处理
@layer base/components/utilities - v4:使用原生CSS层级 - 如果未按正确顺序导入层级,优先级会断裂
- 样式实际已应用,但被工具类覆盖
解决方案选项1:显式定义层级:
css
@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 basecss
@import "tailwindcss";
:root {
--background: hsl(0 0% 100%);
}
body {
background-color: var(--background); /* 不需要@layer */
}适用范围:所有基础样式,不仅限于颜色变量。除非了解CSS层级顺序,否则避免将任何样式包裹在中。
@layer baseQuick Reference
快速参考
| Symptom | Cause | Fix |
|---|---|---|
| Missing | Add |
| Colors all black/white | Double | Use |
| Dark mode not switching | Missing ThemeProvider | Wrap app in |
| Build fails | | Delete file |
| Animation errors | Using | Install |
| 症状 | 原因 | 解决方法 |
|---|---|---|
| 缺少 | 添加 |
| 颜色全为黑/白 | 双重 | 使用 |
| 深色模式无法切换 | 缺少ThemeProvider | 使用 |
| 构建失败 | 存在 | 删除该文件 |
| 动画错误 | 使用了 | 安装 |
What's New in Tailwind v4
Tailwind v4 新特性
OKLCH Color Space (December 2024)
OKLCH颜色空间(2024年12月)
Tailwind v4.0 replaced the entire default color palette with OKLCH, a perceptually uniform color space.
Source: Tailwind v4.0 Release | OKLCH Migration Guide
Why OKLCH:
- Perceptual consistency: HSL's "50% lightness" is visually inconsistent across hues (yellow appears much brighter than blue at same lightness)
- Better gradients: Smooth transitions without muddy middle colors
- Wider gamut: Supports colors beyond sRGB on modern displays
- More vibrant colors: Eye-catching, saturated colors previously limited by sRGB
Browser Support (January 2026):
- Chrome 111+, Firefox 113+, Safari 15.4+, Edge 111+
- Global coverage: 93.1%
Automatic Fallbacks: Tailwind generates sRGB fallbacks for older browsers:
css
.bg-blue-500 {
background-color: #3b82f6; /* sRGB fallback */
background-color: oklch(0.6 0.24 264); /* Modern browsers */
}Custom Colors: When defining custom colors, OKLCH is now preferred:
css
@theme {
/* Modern approach (preferred) */
--color-brand: oklch(0.7 0.15 250);
/* Legacy approach (still works) */
--color-brand: hsl(240 80% 60%);
}Migration: No breaking changes - Tailwind generates fallbacks automatically. For new projects, use OKLCH-aware tooling for custom colors.
Tailwind v4.0将整个默认颜色 palette 替换为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降级方案:
css
.bg-blue-500 {
background-color: #3b82f6; /* sRGB降级方案 */
background-color: oklch(0.6 0.24 264); /* 现代浏览器 */
}自定义颜色:定义自定义颜色时,现在推荐使用OKLCH:
css
@theme {
/* 现代写法(推荐) */
--color-brand: oklch(0.7 0.15 250);
/* 遗留写法(仍可使用) */
--color-brand: hsl(240 80% 60%);
}迁移:无破坏性变更 - Tailwind会自动生成降级方案。对于新项目,使用支持OKLCH的工具定义自定义颜色。
Built-in Features (No Plugin Needed)
内置特性(无需插件)
Container Queries (built-in as of v4.0):
tsx
<div className="@container">
<div className="@md:text-lg @lg:grid-cols-2">
Content responds to container width, not viewport
</div>
</div>Line Clamp (built-in as of v3.3):
tsx
<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>Removed Plugins:
- - Built-in now
@tailwindcss/container-queries - - Built-in since v3.3
@tailwindcss/line-clamp
容器查询(v4.0起内置):
tsx
<div className="@container">
<div className="@md:text-lg @lg:grid-cols-2">
内容响应容器宽度,而非视口宽度
</div>
</div>行数截断(v3.3起内置):
tsx
<p className="line-clamp-3">截断为3行并显示省略号...</p>
<p className="line-clamp-[8]">支持任意值</p>
<p className="line-clamp-(--teaser-lines)">支持CSS变量</p>已移除的插件:
- - 现已内置
@tailwindcss/container-queries - - v3.3起已内置
@tailwindcss/line-clamp
Tailwind v4 Plugins
Tailwind v4 插件
Use directive (NOT or ):
@pluginrequire()@importTypography (for Markdown/CMS content):
bash
pnpm add -D @tailwindcss/typographycss
@import "tailwindcss";
@plugin "@tailwindcss/typography";html
<article class="prose dark:prose-invert">{{ content }}</article>Forms (cross-browser form styling):
bash
pnpm add -D @tailwindcss/formscss
@import "tailwindcss";
@plugin "@tailwindcss/forms";Container Queries (built-in, no plugin needed):
tsx
<div className="@container">
<div className="@md:text-lg">Responds to container width</div>
</div>Common Plugin Errors:
css
/* ❌ WRONG - v3 syntax */
@import "@tailwindcss/typography";
/* ✅ CORRECT - v4 syntax */
@plugin "@tailwindcss/typography";使用指令(不要使用或):
@pluginrequire()@import排版插件(用于Markdown/CMS内容):
bash
pnpm add -D @tailwindcss/typographycss
@import "tailwindcss";
@plugin "@tailwindcss/typography";html
<article class="prose dark:prose-invert">{{ content }}</article>表单插件(跨浏览器表单样式):
bash
pnpm add -D @tailwindcss/formscss
@import "tailwindcss";
@plugin "@tailwindcss/forms";容器查询(内置,无需插件):
tsx
<div className="@container">
<div className="@md:text-lg">响应容器宽度</div>
</div>常见插件错误:
css
/* ❌ 错误 - v3语法 */
@import "@tailwindcss/typography";
/* ✅ 正确 - v4语法 */
@plugin "@tailwindcss/typography";Setup Checklist
搭建检查清单
- installed (NOT postcss)
@tailwindcss/vite - uses
vite.config.tsplugintailwindcss() - has
components.json"config": "" - NO exists
tailwind.config.ts - follows 4-step pattern:
src/index.css- /
:rootat root level (not in @layer).dark - Colors wrapped with
hsl() - maps all variables
@theme inline - uses unwrapped variables
@layer base
-
- ThemeProvider wraps app
- Theme toggle works
- 已安装(不要使用postcss)
@tailwindcss/vite - 使用
vite.config.ts插件tailwindcss() - 中
components.json"config": "" - 不存在
tailwind.config.ts - 遵循四步模式:
src/index.css- /
:root在根级别(不在@layer内部).dark - 颜色使用包裹
hsl() - 映射所有变量
@theme inline - 使用未包裹的变量
@layer base
-
- ThemeProvider已包裹应用
- 主题切换功能正常
File Templates
文件模板
Available in directory:
templates/- index.css - Complete CSS with all color variables
- components.json - shadcn/ui v4 config
- vite.config.ts - Vite + Tailwind plugin
- theme-provider.tsx - Dark mode provider
- utils.ts - utility
cn()
可在目录中获取:
templates/- index.css - 包含所有颜色变量的完整CSS文件
- components.json - shadcn/ui v4配置文件
- vite.config.ts - Vite + Tailwind插件配置
- theme-provider.tsx - 深色模式提供者
- utils.ts - 工具函数
cn()
Migration from v3
从v3迁移
See for complete guide.
reference/migration-guide.mdKey Changes:
- Delete
tailwind.config.ts - Move theme to CSS with
@theme inline - Replace (now built-in:
@tailwindcss/line-clamp)line-clamp-* - Replace with
tailwindcss-animatetw-animate-css - Update plugins: →
require()@plugin
完整指南请参考。
reference/migration-guide.md主要变更:
- 删除
tailwind.config.ts - 使用将主题迁移到CSS
@theme inline - 替换(现已内置:
@tailwindcss/line-clamp)line-clamp-* - 用替换
tw-animate-csstailwindcss-animate - 更新插件:→
require()@plugin
Additional Migration Gotchas
其他迁移注意事项
Automated Migration Tool May Fail
自动迁移工具可能失效
Warning: The utility often fails to migrate configurations.
Source: Community Reports | GitHub Discussion #16642
@tailwindcss/upgradeCommon failures:
- Typography plugin configurations
- Complex theme extensions
- Custom plugin setups
Recommendation: Don't rely on automated migration. Follow manual steps in the migration guide instead.
常见失效场景:
- 排版插件配置
- 复杂的主题扩展
- 自定义插件设置
建议: 不要依赖自动迁移。请遵循迁移指南中的手动步骤。
Default Element Styles Removed
默认元素样式已移除
Tailwind v4 takes a more minimal approach to Preflight, removing default styles for headings, lists, and buttons.
Source: GitHub Discussion #16517 | Medium: Migration Problems
Impact:
- All headings (through
<h1>) render at same size<h6> - Lists lose default padding
- Visual regressions in existing projects
Solutions:
Option 1: Use @tailwindcss/typography for content pages:
bash
pnpm add -D @tailwindcss/typographycss
@import "tailwindcss";
@plugin "@tailwindcss/typography";tsx
<article className="prose dark:prose-invert">
{/* All elements styled automatically */}
</article>Option 2: Add custom base styles:
css
@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; }
}Tailwind v4对Preflight采取了更极简的方式,移除了标题、列表和按钮的默认样式。
来源: GitHub讨论 #16517 | Medium: 迁移问题
影响:
- 所有标题(至
<h1>)显示为相同大小<h6> - 列表失去默认内边距
- 现有项目出现视觉回归
解决方案:
方案1: 对内容页面使用@tailwindcss/typography:
bash
pnpm add -D @tailwindcss/typographycss
@import "tailwindcss";
@plugin "@tailwindcss/typography";tsx
<article className="prose dark:prose-invert">
{/* 所有元素自动应用样式 */}
</article>方案2: 添加自定义基础样式:
css
@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 Setup Complexity
PostCSS设置复杂度
Recommendation: Use plugin for Vite projects instead of PostCSS.
Source: Medium: Migration Problems | GitHub Discussion #15764
@tailwindcss/viteWhy Vite Plugin is Better:
typescript
// ✅ 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 conflictsPostCSS Problems Reported:
- Error: "It looks like you're trying to use tailwindcss directly as a PostCSS plugin"
- Multiple PostCSS plugins required: ,
postcss-import,postcss-advanced-variablestailwindcss/nesting - v4 PostCSS plugin is separate package:
@tailwindcss/postcss
Official Guidance: The Vite plugin is recommended for Vite projects. PostCSS is for legacy setups or non-Vite environments.
为什么Vite插件更好:
typescript
// ✅ Vite插件 - 一行代码,无需PostCSS配置
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [react(), tailwindcss()],
})
// ❌ PostCSS - 多步骤,插件兼容性问题
// 1. 安装@tailwindcss/postcss
// 2. 配置postcss.config.js
// 3. 管理插件顺序
// 4. 调试插件冲突已报告的PostCSS问题:
- 错误: "It looks like you're trying to use tailwindcss directly as a PostCSS plugin"
- 需要多个PostCSS插件: ,
postcss-import,postcss-advanced-variablestailwindcss/nesting - v4的PostCSS插件是单独的包:
@tailwindcss/postcss
官方指导: 对于Vite项目,推荐使用Vite插件。PostCSS适用于遗留设置或非Vite环境。
Visual Changes
视觉变化
Ring Width Default: Changed from 3px to 1px
Source: Medium: Migration Guide
- class is now thinner
ring - Use to match v3 appearance
ring-3
tsx
// 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>默认环宽度: 从3px改为1px
来源: Medium: 迁移指南
- 类现在更细
ring - 使用匹配v3的外观
ring-3
tsx
// v3: 3px环
<button className="ring">按钮</button>
// v4: 1px环(更细)
<button className="ring">按钮</button>
// 匹配v3外观
<button className="ring-3">按钮</button>Reference Documentation
参考文档
- architecture.md - Deep dive into 4-step pattern
- dark-mode.md - Complete dark mode implementation
- common-gotchas.md - Troubleshooting guide
- migration-guide.md - v3 → v4 migration
- architecture.md - 四步模式深度解析
- dark-mode.md - 完整深色模式实现指南
- common-gotchas.md - 故障排除指南
- migration-guide.md - v3 → v4迁移指南
Official Documentation
官方文档
- shadcn/ui Vite Setup: https://ui.shadcn.com/docs/installation/vite
- shadcn/ui Tailwind v4: https://ui.shadcn.com/docs/tailwind-v4
- Tailwind v4 Docs: https://tailwindcss.com/docs
Last Updated: 2026-01-20
Skill Version: 3.0.0
Tailwind v4: 4.1.18 (Latest)
Production: WordPress Auditor (https://wordpress-auditor.webfonts.workers.dev)
Changelog:
- v3.0.0 (2026-01-20): Major research update - added 3 TIER 1 errors (#6-8), expanded migration guide with community findings (TIER 2), added OKLCH color space section, PostCSS complexity warnings, and migration tool limitations
- v2.0.1 (2026-01-03): Production verification
- v2.0.0: Initial release with 5 documented errors
- shadcn/ui Vite设置: https://ui.shadcn.com/docs/installation/vite
- shadcn/ui Tailwind v4: https://ui.shadcn.com/docs/tailwind-v4
- Tailwind v4文档: https://tailwindcss.com/docs
最后更新: 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个一级错误(#6-8),结合社区发现扩展迁移指南(二级内容),添加OKLCH颜色空间章节、PostCSS复杂度警告和迁移工具限制说明
- v2.0.1 (2026-01-03): 生产环境验证
- v2.0.0: 初始发布,包含5种已记录的错误