Tailwind CSS 自定義設計系統:從 Token 到元件庫
10 分鐘閱讀 1,100 字
Tailwind CSS 自定義設計系統:從 Token 到元件庫
Tailwind CSS 不只是一堆工具類別,它更是一個高度可客製化的設計系統框架。透過 tailwind.config.js 的自定義,你可以建立一套完全符合品牌規範的設計系統,同時保留 Tailwind 帶來的開發效率。
為什麼要自定義設計系統
直接使用 Tailwind 預設值雖然快速,但在真實產品中通常需要:
- 使用品牌特定的色彩(非 Tailwind 預設色板)
- 統一的間距和字體規範
- 專案特定的 Breakpoints
- 自訂的動畫效果
設計 Token 的概念
設計 Token 是設計決策的最小單位,如顏色、間距、字體大小。在 Tailwind 中,tailwind.config.js 就是你的 Token 定義檔:
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{html,js,ts,vue,tsx}'],
theme: {
// extend 表示在預設值之上新增,不寫 extend 則完全覆蓋
extend: {
colors: {
// 品牌色系
brand: {
50: '#f0f9ff',
100: '#e0f2fe',
200: '#bae6fd',
300: '#7dd3fc',
400: '#38bdf8',
500: '#0ea5e9', // 主色
600: '#0284c7',
700: '#0369a1',
800: '#075985',
900: '#0c4a6e',
950: '#082f49',
},
// 語意色彩
surface: {
DEFAULT: '#ffffff',
secondary: '#f8fafc',
tertiary: '#f1f5f9',
},
content: {
DEFAULT: '#0f172a',
secondary: '#475569',
tertiary: '#94a3b8',
inverse: '#ffffff',
}
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace'],
},
fontSize: {
// 使用 clamp() 實現響應式字體
'display-lg': ['clamp(2.5rem, 5vw, 4rem)', { lineHeight: '1.1' }],
'display-md': ['clamp(2rem, 4vw, 3rem)', { lineHeight: '1.2' }],
},
spacing: {
'4.5': '1.125rem', // 18px,填補 4(16px)和 5(20px)的空缺
'13': '3.25rem',
'18': '4.5rem',
},
borderRadius: {
'4xl': '2rem',
},
boxShadow: {
'soft': '0 2px 15px -3px rgba(0, 0, 0, 0.07), 0 10px 20px -2px rgba(0, 0, 0, 0.04)',
'card': '0 0 0 1px rgba(0,0,0,.03), 0 2px 4px rgba(0,0,0,.05), 0 12px 24px rgba(0,0,0,.05)',
},
animation: {
'fade-in': 'fadeIn 0.3s ease-in-out',
'slide-up': 'slideUp 0.3s ease-out',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
slideUp: {
'0%': { transform: 'translateY(10px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
}
}
}
},
plugins: []
}CSS 變數整合:深色模式支援
/* src/styles/tokens.css */
:root {
--color-brand: theme('colors.brand.500');
--color-surface: theme('colors.surface.DEFAULT');
--color-content: theme('colors.content.DEFAULT');
}
.dark {
--color-surface: #0f172a;
--color-surface-secondary: #1e293b;
--color-content: #f8fafc;
--color-content-secondary: #94a3b8;
}// tailwind.config.js
extend: {
colors: {
// 使用 CSS 變數,自動響應深色模式
adaptive: {
surface: 'var(--color-surface)',
content: 'var(--color-content)',
}
}
}元件層(Components Layer)
使用 @layer components 建立可複用的元件類別,保留 Tailwind 的 JIT 和 PurgeCSS 優化:
/* src/styles/components.css */
@layer components {
/* 按鈕基礎樣式 */
.btn {
@apply inline-flex items-center justify-center
px-4 py-2 rounded-lg font-medium text-sm
transition-all duration-200 cursor-pointer
focus:outline-none focus:ring-2 focus:ring-offset-2
disabled:opacity-50 disabled:cursor-not-allowed;
}
.btn-primary {
@apply btn bg-brand-500 text-white
hover:bg-brand-600 active:bg-brand-700
focus:ring-brand-500;
}
.btn-secondary {
@apply btn bg-surface-secondary text-content
border border-slate-200
hover:bg-surface-tertiary
focus:ring-brand-500;
}
.btn-ghost {
@apply btn text-content-secondary
hover:bg-surface-secondary
focus:ring-brand-500;
}
/* 卡片 */
.card {
@apply bg-white rounded-2xl shadow-card p-6;
}
/* 表單輸入 */
.input {
@apply w-full px-3 py-2 text-sm
border border-slate-200 rounded-lg
bg-white text-content
placeholder-content-tertiary
focus:outline-none focus:ring-2 focus:ring-brand-500 focus:border-transparent
transition-shadow duration-200;
}
.input-error {
@apply input border-red-300 focus:ring-red-500;
}
}工具類別層(Utilities Layer)
@layer utilities {
/* 文字截斷 */
.text-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* 滾動行為 */
.scroll-smooth-x {
scroll-behavior: smooth;
overflow-x: auto;
scrollbar-width: thin;
}
}在 Vue 元件中使用
<template>
<div class="card animate-fade-in">
<h2 class="text-display-md text-content font-bold mb-4">
{{ title }}
</h2>
<p class="text-content-secondary text-clamp-2">
{{ description }}
</p>
<div class="flex gap-3 mt-6">
<button class="btn-primary">
開始使用
</button>
<button class="btn-ghost">
了解更多
</button>
</div>
</div>
</template>建立設計系統文件
搭配 Storybook 或簡單的靜態頁面記錄設計系統:
# 安裝 Storybook(Vue)
npx storybook@latest init
# 安裝 Tailwind 插件
npm install -D @storybook/addon-styling-webpackTailwind Plugins:擴充功能
// tailwind.config.js
import plugin from 'tailwindcss/plugin'
export default {
plugins: [
// 官方插件
require('@tailwindcss/typography'),
require('@tailwindcss/forms'),
// 自訂插件:新增 text-shadow 工具類
plugin(function({ addUtilities, theme }) {
addUtilities({
'.text-shadow-sm': { textShadow: '0 1px 2px rgba(0,0,0,0.1)' },
'.text-shadow': { textShadow: '0 2px 4px rgba(0,0,0,0.15)' },
'.text-shadow-none': { textShadow: 'none' },
})
})
]
}總結
Tailwind 的強大不在於預設的工具類別,而在於它讓設計 Token 與程式碼緊密整合的架構。透過 tailwind.config.js 定義品牌色彩和間距、用 @layer components 封裝元件樣式、搭配 CSS 變數支援深色模式,你可以在保持 Tailwind 開發效率的同時,建立出一套完整、一致的設計系統。
分享這篇文章