跳转到内容

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 理念让样式开发更加直观和灵活,掌握主题系统和插件开发将让你构建出更加精美和高效的界面。


相关阅读: