1. React + Tailwind:动态 className
在 React 中,样式通过 className prop 传递。Tailwind 工具类是静态字符串,但实际开发中经常需要根据 state/props 动态切换类名。
基础动态类名
// ❌ 错误:不能用字符串拼接生成类名(v4 需要完整类名才能被扫描)
const size = 'lg';
<div className={`text-${size}`}> // ❌ text-lg 可能不会生成
// ✅ 正确:使用完整的类名字符串
const sizeClass = size === 'lg' ? 'text-lg' : 'text-sm';
<div className={sizeClass}>
// ✅ 模板字符串(但变量必须是完整类名)
<button
className={`px-4 py-2 rounded-lg ${isActive ? 'bg-cyan-500 text-white' : 'bg-gray-100 text-gray-600'}`}
>
JIT 扫描限制:Tailwind 通过静态扫描源码找出使用的类名。如果你动态拼接类名(如 `text-${color}`),JIT 无法识别,这些类不会被包含在输出 CSS 中。必须使用完整的类名字符串。
2. clsx / cn 工具函数
clsx 是一个轻量级工具库,专门处理条件类名合并。cn 是 shadcn/ui 推荐的封装,在 clsx 基础上加了 tailwind-merge 去重。
// 安装
npm install clsx tailwind-merge
// utils/cn.ts —— shadcn/ui 推荐的 cn 工具函数
import { clsx, ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
// 使用示例
import { cn } from '@/utils/cn'
// 条件类名(clsx)
cn(
'px-4 py-2 rounded-lg font-medium', // 始终有
isActive && 'bg-cyan-500 text-white', // 条件有
!isActive && 'bg-gray-100 text-gray-600', // 另一条件
size === 'sm' && 'text-sm',
size === 'lg' && 'text-lg px-6',
)
// 结果示例:'px-4 py-2 rounded-lg font-medium bg-cyan-500 text-white'
// tailwind-merge 解决冲突(同一属性多个值)
cn('px-4 py-2', 'p-6') // → 'p-6'(p-6 覆盖 px-4 py-2)
cn('text-blue-500', 'text-cyan-500') // → 'text-cyan-500'
在 React 组件中使用 cn
import { cn } from '@/utils/cn'
interface ButtonProps {
variant?: 'primary' | 'outline' | 'ghost'
size?: 'sm' | 'md' | 'lg'
className?: string
children: React.ReactNode
}
export function Button({
variant = 'primary',
size = 'md',
className,
children,
...props
}: ButtonProps) {
return (
<button
className={cn(
// 基础样式
'inline-flex items-center justify-center rounded-lg font-medium',
'transition-all duration-200 focus-visible:outline-none',
'focus-visible:ring-2 focus-visible:ring-offset-2',
// variant
variant === 'primary' && 'bg-cyan-500 text-white hover:bg-cyan-600 focus-visible:ring-cyan-500',
variant === 'outline' && 'border-2 border-cyan-500 text-cyan-600 hover:bg-cyan-50',
variant === 'ghost' && 'text-gray-600 hover:bg-gray-100 hover:text-gray-900',
// size
size === 'sm' && 'text-xs px-3 py-1.5',
size === 'md' && 'text-sm px-4 py-2',
size === 'lg' && 'text-base px-6 py-3',
// 允许外部覆盖(tailwind-merge 处理冲突)
className
)}
{...props}
>
{children}
</button>
)
}
// 使用
<Button variant="primary" size="lg">提交</Button>
<Button variant="outline" className="w-full">取消</Button>
3. Vue 3 + Tailwind
<!-- Vue 3 动态类名绑定 -->
<template>
<!-- :class 接受对象/数组 -->
<button
:class="[
'px-4 py-2 rounded-lg font-medium transition-colors',
isActive ? 'bg-cyan-500 text-white' : 'bg-gray-100 text-gray-700',
size === 'lg' ? 'text-lg px-6 py-3' : 'text-sm',
]"
@click="toggle"
>
{{ label }}
</button>
<!-- 对象语法 -->
<div :class="{
'opacity-50 cursor-not-allowed': disabled,
'hover:scale-105': !disabled,
'bg-cyan-500': isPrimary,
'bg-gray-200': !isPrimary,
}"></div>
</template>
<script setup>
import { ref } from 'vue'
const isActive = ref(false)
const toggle = () => isActive.value = !isActive.value
</script>
4. Next.js 15 配置
# 创建 Next.js 15 项目(选择 Tailwind CSS)
npx create-next-app@latest my-app
# 选项:✔ TypeScript ✔ ESLint ✔ Tailwind CSS ✔ App Router
# 或手动安装到已有项目
npm install tailwindcss @tailwindcss/postcss postcss
/* app/globals.css —— Next.js 15 + Tailwind v4 */
@import "tailwindcss";
@theme {
--font-sans: var(--font-geist-sans); /* Next.js 内置字体 */
}
// app/layout.tsx
import './globals.css'
import { Geist } from 'next/font/google'
const geist = Geist({ subsets: ['latin'] })
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="zh-CN">
<body className={cn(geist.className, 'bg-background text-foreground')}>
{children}
</body>
</html>
)
}
5. VS Code IntelliSense 插件配置
安装 Tailwind CSS IntelliSense 扩展(bradlc.vscode-tailwindcss)可以获得自动补全、悬停预览、语法检查等功能。
// .vscode/settings.json
{
// 让 cn() 函数内也有自动补全
"tailwindCSS.experimental.classRegex": [
["cn\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
["clsx\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
],
// 关联文件类型
"tailwindCSS.includeLanguages": {
"plaintext": "html"
}
}
本章小结:React 项目中,cn(clsx + tailwind-merge)是动态类名的最佳工具;Vue 用 :class 对象/数组语法;Next.js 项目在创建时选择 Tailwind 选项即可自动配置。VS Code 安装 IntelliSense 插件后,Tailwind 的开发体验接近原生 CSS 编辑器。