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 安裝
# 安裝 v4.0
npm install tailwindcss @tailwindcss/vite
# 刪除舊版本配置文件
rm tailwind.config.js postcss.config.js// vite.config.ts
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()]
})/* 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 基礎主題配置
@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 語義化顏色命名
@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 顏色變體生成
@theme {
/* v4.0 自動生成顏色變體 */
--color-primary: #3b82f6;
/* 自動生成的變體 */
/* primary-50, primary-100, ..., primary-950 */
/* primary-light, primary-dark, primary-opacity */
}自定義顏色變體:
@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 變量
/* 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 動態主題切換
// 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 }
}<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 基礎工具類
@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 響應式工具類
@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 條件工具類
@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 插件結構
// 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 中使用插件
// 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 動態插件
// 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 體積
// 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 樹搖優化
@import "tailwindcss";
@theme {
/* 只定義需要的主題變量 */
--color-primary: #3b82f6;
--color-background: #ffffff;
--color-foreground: #1f2937;
}
/* 只添加需要的工具類 */
@layer utilities {
.custom-toolbar {
/* ... */
}
}6.3 緩存策略
// vite.config.ts
export default defineConfig({
build: {
rollupOptions: {
output: {
assetFileNames: 'assets/[name]-[hash].[ext]',
chunkFileNames: 'js/[name]-[hash].js'
}
}
}
})6.4 關鍵 CSS 提取
// 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 集成
<!-- 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 類型支持
// 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.vue/* src/style.css */
@import "tailwindcss";
@import "./theme/colors.css";
@import "./theme/typography.css";
@import "./theme/spacing.css";
@import "./theme/shadows.css";8.2 組件樣式策略
/* 組件內樣式 */
<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 性能監控
// 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 理念讓樣式開發更加直觀和靈活,掌握主題系統和插件開發將讓你構建出更加精美和高效的界面。
相關閱讀: