Tailwind CSS v4.0 主题系统与自定义插件开发实战 2026 | 样式工程化指南

Tailwind CSS v4.0 是一次重大重构,引入了原生 CSS 变量支持、零配置 CSS-first 模式和强大的插件系统。本文将深入 v4.0 的核心特性,从主题系统到自定义插件开发,全面掌握样式工程化技能。
一、Tailwind CSS v4.0 核心变化
1.1 v4.0 vs v3.x
| 特性 | v3.x | v4.0 |
|---|---|---|
| 配置方式 | tailwind.config.js | CSS 变量 + 可选配置 |
| 样式注入 | PostCSS 插件 | 原生 CSS @import |
| 主题系统 | 对象配置 | CSS 变量 |
| 自定义工具类 | @layer utilities | 原生 CSS |
| JIT 模式 | 需要启用 | 默认开启 |
| CSS 变量 | 部分支持 | 完全支持 |
| 插件系统 | 函数式 | 对象式 |
1.2 v4.0 安装
bash
# 安装 v4.0
npm install tailwindcss @tailwindcss/vite
# 删除旧版本配置文件
rm tailwind.config.js postcss.config.jstypescript
// vite.config.ts
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()]
})css
/* src/style.css */
@import "tailwindcss";
@theme {
--color-primary: #3b82f6;
--color-primary-dark: #2563eb;
--font-sans: 'Inter', system-ui, sans-serif;
--radius: 0.5rem;
}二、主题系统深度解析
2.1 基础主题配置
css
@theme {
/* 颜色系统 */
--color-background: #ffffff;
--color-foreground: #1f2937;
--color-primary: #3b82f6;
--color-primary-foreground: #ffffff;
--color-secondary: #6b7280;
--color-secondary-foreground: #ffffff;
/* 字体系统 */
--font-sans: 'Inter', system-ui, -apple-system, sans-serif;
--font-serif: Georgia, 'Times New Roman', serif;
--font-mono: 'Fira Code', monospace;
/* 字号系统 */
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
/* 间距系统 */
--spacing-1: 0.25rem;
--spacing-2: 0.5rem;
--spacing-3: 0.75rem;
--spacing-4: 1rem;
--spacing-8: 2rem;
--spacing-16: 4rem;
/* 圆角系统 */
--radius-sm: 0.25rem;
--radius: 0.5rem;
--radius-lg: 0.75rem;
--radius-xl: 1rem;
--radius-2xl: 1.5rem;
/* 阴影系统 */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
/* 过渡系统 */
--transition-fast: 150ms ease;
--transition-normal: 200ms ease;
--transition-slow: 300ms ease;
/* Z-index 系统 */
--z-dropdown: 1000;
--z-sticky: 1020;
--z-fixed: 1030;
--z-modal-backdrop: 1040;
--z-modal: 1050;
}2.2 语义化颜色命名
css
@theme {
/* 语义化颜色 */
--color-success: #10b981;
--color-success-light: #d1fae5;
--color-warning: #f59e0b;
--color-warning-light: #fef3c7;
--color-error: #ef4444;
--color-error-light: #fee2e2;
--color-info: #06b6d4;
--color-info-light: #cffafe;
/* 状态颜色 */
--color-disabled: #9ca3af;
--color-hover: rgba(0, 0, 0, 0.05);
--color-focus: rgba(59, 130, 246, 0.2);
/* 层级颜色 */
--color-surface: #f9fafb;
--color-surface-elevated: #ffffff;
--color-border: #e5e7eb;
}2.3 颜色变体生成
css
@theme {
/* v4.0 自动生成颜色变体 */
--color-primary: #3b82f6;
/* 自动生成的变体 */
/* primary-50, primary-100, ..., primary-950 */
/* primary-light, primary-dark, primary-opacity */
}自定义颜色变体:
css
@theme {
--color-primary: #3b82f6;
--color-primary-light: #60a5fa;
--color-primary-dark: #2563eb;
--color-primary-opacity-50: rgba(59, 130, 246, 0.5);
}三、CSS 变量与动态主题
3.1 使用 CSS 变量
css
/* src/style.css */
@import "tailwindcss";
@theme {
--color-primary: #3b82f6;
--radius: 0.5rem;
}
/* 自定义工具类 */
.btn-primary {
background-color: var(--color-primary);
border-radius: var(--radius);
color: white;
padding: var(--spacing-4);
}
/* 响应式工具类 */
@media (min-width: 768px) {
.btn-large {
padding: var(--spacing-6);
}
}3.2 动态主题切换
typescript
// composables/useTheme.ts
import { ref, watch } from 'vue'
type Theme = 'light' | 'dark'
const currentTheme = ref<Theme>('light')
export function useTheme() {
const themes = {
light: {
'--color-background': '#ffffff',
'--color-foreground': '#1f2937',
'--color-surface': '#f9fafb',
'--color-border': '#e5e7eb'
},
dark: {
'--color-background': '#111827',
'--color-foreground': '#f3f4f6',
'--color-surface': '#1f2937',
'--color-border': '#374151'
}
}
function setTheme(theme: Theme) {
currentTheme.value = theme
const root = document.documentElement
Object.entries(themes[theme]).forEach(([key, value]) => {
root.style.setProperty(key, value)
})
localStorage.setItem('theme', theme)
}
function toggleTheme() {
setTheme(currentTheme.value === 'light' ? 'dark' : 'light')
}
// 初始化主题
const savedTheme = localStorage.getItem('theme') as Theme | null
if (savedTheme) {
setTheme(savedTheme)
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
setTheme('dark')
}
// 监听系统主题变化
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
if (!localStorage.getItem('theme')) {
setTheme(e.matches ? 'dark' : 'light')
}
})
return { currentTheme, setTheme, toggleTheme }
}vue
<script setup>
import { useTheme } from '@/composables/useTheme'
const { currentTheme, toggleTheme } = useTheme()
</script>
<template>
<button
@click="toggleTheme"
class="p-4 rounded-lg bg-primary text-white"
>
{{ currentTheme === 'light' ? '切换深色' : '切换浅色' }}
</button>
</template>四、自定义工具类开发
4.1 基础工具类
css
@import "tailwindcss";
@theme {
--color-primary: #3b82f6;
}
/* 自定义工具类 */
@layer utilities {
.text-balance {
text-wrap: balance;
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
}4.2 响应式工具类
css
@import "tailwindcss";
@theme {
--color-primary: #3b82f6;
}
@layer utilities {
.padding-safe {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
/* 响应式变体 */
@media (min-width: 768px) {
.padding-safe-md {
padding-top: calc(env(safe-area-inset-top) + 1rem);
}
}
}4.3 条件工具类
css
@import "tailwindcss";
@theme {
--color-primary: #3b82f6;
}
@layer utilities {
.animate-bounce-slow {
animation: bounce 2s infinite;
}
.animate-pulse-fast {
animation: pulse 0.5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
}
@keyframes bounce {
0%, 100% {
transform: translateY(-25%);
animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
}
50% {
transform: translateY(0);
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
}五、自定义插件开发
5.1 插件结构
typescript
// tailwind/plugins/button.ts
import type { Plugin } from 'tailwindcss'
export function buttonPlugin(): Plugin {
return {
name: 'button-plugin',
// 扩展主题
theme: {
extend: {
colors: {
button: {
primary: '#3b82f6',
secondary: '#6b7280',
success: '#10b981',
error: '#ef4444'
}
},
padding: {
button: '0.5rem 1rem'
},
borderRadius: {
button: '0.5rem'
}
}
},
// 添加工具类
utilities: {
'.btn-primary': {
backgroundColor: '#3b82f6',
color: '#ffffff',
padding: '0.5rem 1rem',
borderRadius: '0.5rem',
transition: 'all 200ms ease',
'&:hover': {
backgroundColor: '#2563eb'
},
'&:active': {
transform: 'scale(0.98)'
},
'&:disabled': {
opacity: '0.5',
cursor: 'not-allowed'
}
},
'.btn-secondary': {
backgroundColor: '#6b7280',
color: '#ffffff',
padding: '0.5rem 1rem',
borderRadius: '0.5rem',
transition: 'all 200ms ease',
'&:hover': {
backgroundColor: '#4b5563'
}
}
},
// 添加组件类
components: {
'.btn': {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
gap: '0.5rem',
fontWeight: '500',
fontSize: '0.875rem',
cursor: 'pointer',
border: 'none',
'&:focus': {
outline: 'none',
boxShadow: '0 0 0 3px rgba(59, 130, 246, 0.3)'
}
}
}
}
}5.2 在 Vite 中使用插件
typescript
// vite.config.ts
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
import { buttonPlugin } from './tailwind/plugins/button'
export default defineConfig({
plugins: [
tailwindcss({
plugins: [buttonPlugin()]
})
]
})5.3 动态插件
typescript
// tailwind/plugins/responsive.ts
import type { Plugin } from 'tailwindcss'
export function responsivePlugin(breakpoints: Record<string, string>): Plugin {
return {
name: 'responsive-plugin',
theme: {
extend: {
screens: breakpoints
}
},
utilities: {
// 为每个断点生成响应式工具类
...Object.entries(breakpoints).reduce((acc, [name]) => {
acc[`.hide-${name}`] = {
[`@media (min-width: ${breakpoints[name]})`]: {
display: 'none'
}
}
return acc
}, {})
}
}
}
// 使用
tailwindcss({
plugins: [
responsivePlugin({
sm: '640px',
md: '768px',
lg: '1024px',
xl: '1280px'
})
]
})六、性能优化
6.1 减少 CSS 体积
typescript
// vite.config.ts
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [
tailwindcss({
// 禁用未使用的工具类(生产构建)
content: [
'./index.html',
'./src/**/*.{vue,js,ts,jsx,tsx}'
],
// 仅包含需要的工具类
corePlugins: {
preflight: true, // 保留基础样式重置
container: false, // 不需要容器类
aspectRatio: true, // 需要宽高比
animation: true // 需要动画
}
})
]
})6.2 树摇优化
css
@import "tailwindcss";
@theme {
/* 只定义需要的主题变量 */
--color-primary: #3b82f6;
--color-background: #ffffff;
--color-foreground: #1f2937;
}
/* 只添加需要的工具类 */
@layer utilities {
.custom-toolbar {
/* ... */
}
}6.3 缓存策略
typescript
// vite.config.ts
export default defineConfig({
build: {
rollupOptions: {
output: {
assetFileNames: 'assets/[name]-[hash].[ext]',
chunkFileNames: 'js/[name]-[hash].js'
}
}
}
})6.4 关键 CSS 提取
typescript
// vite.config.ts
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
import { extractCritical } from '@tailwindcss/vite'
export default defineConfig({
plugins: [
tailwindcss({
experimental: {
extractCritical: true
}
})
]
})七、与框架深度集成
7.1 Vue 3 集成
vue
<!-- src/components/Button.vue -->
<script setup lang="ts">
interface Props {
variant?: 'primary' | 'secondary' | 'success' | 'error'
size?: 'sm' | 'md' | 'lg'
disabled?: boolean
}
withDefaults(defineProps<Props>(), {
variant: 'primary',
size: 'md',
disabled: false
})
</script>
<template>
<button
:class="[
'btn',
`btn-${variant}`,
`btn-${size}`,
{ 'btn-disabled': disabled }
]"
:disabled="disabled"
>
<slot />
</button>
</template>
<style scoped>
.btn-sm {
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
}
.btn-md {
padding: 0.5rem 1rem;
font-size: 0.875rem;
}
.btn-lg {
padding: 0.75rem 1.5rem;
font-size: 1rem;
}
.btn-disabled {
opacity: 0.5;
cursor: not-allowed;
}
</style>7.2 TypeScript 类型支持
typescript
// tailwind/types.ts
import type { Theme } from 'tailwindcss'
declare module 'tailwindcss' {
interface Theme {
colors: Theme['colors'] & {
button: {
primary: string
secondary: string
success: string
error: string
}
}
}
}八、最佳实践
8.1 主题组织
src/
├── style.css # 主样式文件
├── theme/
│ ├── colors.css # 颜色主题
│ ├── typography.css # 字体主题
│ ├── spacing.css # 间距主题
│ └── shadows.css # 阴影主题
└── components/
└── Button.vuecss
/* src/style.css */
@import "tailwindcss";
@import "./theme/colors.css";
@import "./theme/typography.css";
@import "./theme/spacing.css";
@import "./theme/shadows.css";8.2 组件样式策略
css
/* 组件内样式 */
<style scoped>
/* 使用 CSS 变量 */
.component {
background-color: var(--color-surface);
border-radius: var(--radius);
}
/* 响应式 */
@media (min-width: 768px) {
.component {
padding: var(--spacing-6);
}
}
</style>8.3 性能监控
typescript
// vite.config.ts
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [
tailwindcss({
// 开发模式下输出性能报告
experimental: {
performance: true
}
})
]
})九、总结
- ✅ 掌握 Tailwind CSS v4.0 核心变化(CSS-first、零配置)
- ✅ 深入主题系统(颜色、字体、间距、阴影等)
- ✅ 实现动态主题切换(浅色/深色模式)
- ✅ 开发自定义工具类(响应式、条件、动画)
- ✅ 编写自定义插件(主题扩展、工具类、组件)
- ✅ 性能优化(体积控制、树摇、缓存)
- ✅ 与 Vue 3 和 TypeScript 深度集成
Tailwind CSS v4.0 的 CSS-first 理念让样式开发更加直观和灵活,掌握主题系统和插件开发将让你构建出更加精美和高效的界面。
相关阅读: