跳轉到內容

Tailwind CSS v4.0 主題系統與自定義插件開發實戰 2026 | 樣式工程化指南

Tailwind CSS v4.0 主題與插件開發

Tailwind CSS v4.0 是一次重大重構,引入了原生 CSS 變量支持、零配置 CSS-first 模式和強大的插件系統。本文將深入 v4.0 的核心特性,從主題系統到自定義插件開發,全面掌握樣式工程化技能。


一、Tailwind CSS v4.0 核心變化

1.1 v4.0 vs v3.x

特性v3.xv4.0
配置方式tailwind.config.jsCSS 變量 + 可選配置
樣式注入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.js
typescript
// 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.vue
css
/* 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 理念讓樣式開發更加直觀和靈活,掌握主題系統和插件開發將讓你構建出更加精美和高效的界面。


相關閱讀:

最後更新於: