面試:設計系統 — 用 TailwindCSS 架構可規模化的 Design System | TailwindCSS 完整教學
觀念、技術、除錯三關都過了,面試最後、也是層級最高的一關,是 設計系統(Design System)。這一篇我們把視野從「一個 class 怎麼寫」拉高到「如何用 Tailwind 撐起一整個產品的設計語言」——@theme 的 token 分層、多品牌/白牌的主題策略、CVA 的元件變體抽象、
@apply與元件抽取的取捨、跨團隊一致性約束、設計師與工程師的 Figma tokens 交接、以及大型專案的遷移權衡。本篇用 Q&A 精選 10 題設計題,每題都給你「題目 → 思路 → 示例(含可執行程式碼)」。這是 50 篇 TailwindCSS 完整教學 的壓軸,我們一起把最後這關收好。
前言
前一篇《面試:除錯題》,我們練的是「線上出事了怎麼查」——那是戰術層級的能力。而這一篇要練的是戰略層級:當面試官問你「如果讓你從零規劃一套設計系統,你會怎麼用 Tailwind 架構?」,他考的不是你會不會寫 class,而是你有沒有系統性的架構思維——能不能把顏色、間距、元件、主題、團隊協作,組織成一套可規模化、可維護、能撐十年的設計語言。
設計題和前幾類題最大的不同,是它幾乎沒有標準答案,只有權衡(trade-off)。「該用 @apply 還是元件抽取?」「多品牌要不要拆成多份 CSS?」「元件庫該自製還是用 shadcn?」——這些問題的正解永遠是「看情況」,而面試官真正想聽的,是你能不能先問清楚需求、再講清楚每個選擇的代價。這種「先釐清約束、再做決策、並說得出為什麼」的能力,正是 Senior 與 Tech Lead 的分水嶺。
本篇聚焦 TailwindCSS v4 的設計系統實務,適合準備資深(Senior)、Tech Lead、前端架構師面試的工程師,也適合正在為團隊建立 Tailwind 規範、想把零散經驗系統化的人。本篇你將學到:
- Token 分層:用
@theme規劃「原始 → 語義 → 元件」三層 token,以及 v4 如何取代 v3 的tailwind.config.js - 主題策略:多品牌/白牌的 CSS 變數覆蓋架構、執行時動態切換、暗色模式的分層做法
- 元件抽象:CVA 管理變體、
@apply/元件抽取/Plugin 的決策樹、shadcn/Radix/Headless 的選型 - 團隊協作:跨團隊一致性約束(型別、Lint、CI)、設計師↔工程師的 Figma tokens 交接、大型專案遷移策略
面試題精選
以下 10 題涵蓋設計系統面試最高頻的架構題。每題都用 題目 → 思路 → 示例 的結構呈現——「題目」是面試官會問的問法、「思路」是答題時該講的權衡與方向、「示例」是附上可執行程式碼的具體落地。面試時能照這個結構答,就展現了架構師該有的系統思維。
題目1:請用 Tailwind 從零架構一套設計系統,說明從 Token 到元件的層次
思路
這題是設計系統的開場總覽題,答題主軸是「分層」。一套設計系統不是一堆 class,而是由下而上的層次結構:最底層是設計 Token(色彩、字體、間距的系統化表達),往上是基礎元件(Button、Input),再往上是複合元件(Form、Card、Modal),最後是模式與頁面模板。面試官想聽你能不能講清楚「每一層負責什麼、上層只依賴下層」的單向依賴關係。而 Token 本身又要再細分為原始(Primitive)、語義(Semantic)、元件(Component) 三層,這是全題的核心。
示例
先講清楚整體層次,再落地到 v4 的 @theme:
設計系統層次(由下而上):
─────────────────────────────────────────
Layer 1 設計 Token 原始 → 語義 → 元件(三層)
Layer 2 基礎元件 Button / Input / Badge(無業務邏輯)
Layer 3 複合元件 Form / Card / Modal(由基礎元件組合)
Layer 4 模式 Search Bar / Auth Form(常見 UI 問題)
Layer 5 頁面模板 Dashboard / Blog(複合元件的頁面組合)
─────────────────────────────────────────
原則:上層只依賴下層,下層不知道上層存在
Token 的三層落地(v4)——原始層放 @theme 生成 utility,語義層放 :root 供覆蓋:
/* tokens.css */
@import "tailwindcss";
@theme {
/* Layer 1a:原始 token(Primitive)——純調色盤,無語義 */
--color-gray-50: #f9fafb;
--color-gray-600: #4b5563;
--color-gray-900: #111827;
--color-blue-600: #2563eb;
--color-blue-700: #1d4ed8;
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
}
:root {
/* Layer 1b:語義 token(Semantic)——元件只引用這一層 */
--text-primary: var(--color-gray-900);
--text-secondary: var(--color-gray-600);
--brand-primary: var(--color-blue-600);
--brand-hover: var(--color-blue-700);
}
答題判準:能講出「原始 token 沒語義、語義 token 才有意義、元件永遠只碰語義層」,就贏過只會列 class 的人。
題目2:設計 Token 是什麼?為何 v4 的 @theme 比 v3 的 tailwind.config.js 更適合做設計系統?
思路
設計 Token(Design Tokens)是設計決策的單一來源(single source of truth)——把「品牌主色是這個藍」這種決策從程式碼中抽出來、命名、集中管理,讓 Figma 與程式碼指向同一份定義。這題的重點是對比 v3 與 v4 的設定方式:v3 把 token 寫在 JavaScript 設定檔(tailwind.config.js),v4 直接寫在 CSS 的 @theme 裡。面試官想聽的是你懂「為什麼 v4 更適合設計系統」——關鍵在於 @theme 同時產生 utility class 與 CSS 變數,而 CSS 變數能在執行時被覆蓋,這正是主題切換的基礎。
示例
同一組 token,v3 與 v4 的寫法對比:
// v3:寫在 JS 設定檔
module.exports = {
theme: {
extend: {
colors: { brand: { 500: '#3b82f6', 600: '#2563eb' } },
fontFamily: { sans: ['Inter', 'system-ui'] },
},
},
}
/* v4:直接寫在 CSS,@theme 同時生成 utility 與 CSS 變數 */
@import "tailwindcss";
@theme {
--color-brand-500: #3b82f6; /* 生成 bg-brand-500 等 utility */
--color-brand-600: #2563eb; /* 同時是真實 CSS 變數 var(--color-brand-600) */
--font-family-sans: 'Inter', system-ui, sans-serif;
}
v4 更適合設計系統的四個理由:
v4 @theme vs v3 config:
─────────────────────────────────────────
1. 統一在 CSS 管理,不用 JS 設定檔
2. @theme 同時產生 CSS 變數 + utility class
3. CSS 變數可在執行時覆蓋 → 主題切換更簡單
4. 設計師不用懂 Node.js 也能改
─────────────────────────────────────────
判準:能點出「@theme 同時是 utility 也是可執行時覆蓋的 CSS 變數」,就抓到了 v4 做設計系統的精髓。
題目3:如何處理多品牌(Multi-brand)或白牌(White-label)主題?
思路
這是 SaaS 與白牌產品的核心設計題,答題主軸是「元件只認語義 token,品牌只換語義 token 的值」。錯誤做法是為每個品牌拆一整份 CSS 或一套元件——那會讓維護成本爆炸。正解是:元件只用語義層(--brand-primary),品牌則透過 data-brand 屬性選擇器覆蓋語義變數的值。切換品牌時只要改根元素的一個屬性,整個畫面就跟著換,不用重編譯、不用換 class。進階題會問「品牌 token 來自後端怎麼辦」,答案是執行時用 JS 動態注入 CSS 變數。
示例
語義層預設值 + 各品牌覆蓋:
/* 語義層:預設品牌 */
:root {
--brand-primary: #3b82f6;
--brand-radius: 0.5rem;
--brand-font: 'Inter', sans-serif;
}
/* 品牌 A:科技感(更方正) */
[data-brand="brand-a"] {
--brand-primary: #6366f1;
--brand-radius: 0.25rem;
}
/* 品牌 B:友善感(更圓潤) */
[data-brand="brand-b"] {
--brand-primary: #10b981;
--brand-radius: 1rem;
}
@theme 讓 utility 指向語義變數,並用 color-mix() 自動推導衍生色:
@import "tailwindcss";
@theme {
--color-brand: var(--brand-primary);
/* 從單一主色自動推導 hover/light,少維護一堆 token */
--color-brand-dark: color-mix(in srgb, var(--brand-primary) 85%, black);
--radius-brand: var(--brand-radius);
}
切換品牌只要改根元素;白牌則從 API 執行時注入:
// 白牌:從 API 取品牌 token,執行時動態注入 CSS 變數
async function applyBrand(brandId: string) {
const tokens = await fetch(`/api/brands/${brandId}/tokens`).then(r => r.json())
const root = document.documentElement
Object.entries(tokens).forEach(([k, v]) => root.style.setProperty(`--brand-${k}`, v as string))
root.setAttribute('data-brand', brandId)
}
判準:能說「元件只碰語義層、切品牌只換值不換 class」,並補上執行時注入,就是完整的白牌答案。
題目4:什麼是 CVA?它如何解決元件變體(variant)的維護問題?
思路
當一個 Button 有 primary/secondary/ghost 三種外觀 × sm/md/lg 三種尺寸,若在 JSX 裡用三元運算拼 class,程式碼會又臭又長、型別不安全、還會有 class 衝突。CVA(Class Variance Authority) 就是為此而生:它讓你把元件的所有外觀集中宣告成 variants、compoundVariants、defaultVariants,並自動用 VariantProps 推導 TypeScript 型別。這題面試官想聽你能不能說出 CVA 的三種欄位各自的用途,以及它帶來的型別安全與可維護性。
示例
先看沒有 CVA 的痛:
// ❌ 三元運算堆疊:難讀、型別不安全、class 易衝突
<button className={`inline-flex rounded-md font-medium
${variant === 'primary' ? 'bg-blue-600 text-white hover:bg-blue-700' : ''}
${variant === 'ghost' ? 'hover:bg-gray-100 text-gray-700' : ''}
${size === 'sm' ? 'px-3 py-1.5 text-sm' : 'px-4 py-2 text-sm'}`}>
用 CVA 集中管理:
import { cva, type VariantProps } from 'class-variance-authority'
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md font-medium transition-colors',
{
variants: {
variant: {
primary: 'bg-blue-600 text-white hover:bg-blue-700',
ghost: 'bg-transparent text-gray-700 hover:bg-gray-100',
},
size: { sm: 'px-3 py-1.5 text-sm', md: 'px-4 py-2 text-sm', lg: 'px-6 py-3 text-base' },
},
// 複合變體:特定組合才加的樣式
compoundVariants: [{ variant: 'primary', size: 'lg', class: 'shadow-md' }],
defaultVariants: { variant: 'primary', size: 'md' },
}
)
// 型別自動推導:傳錯 variant 會編譯報錯
type ButtonVariants = VariantProps<typeof buttonVariants>
判準:能講出 variants / compoundVariants / defaultVariants 三者用途,並點出 VariantProps 帶來型別安全,就是高分答案。
題目5:元件的預設 class 被外部傳入的 class 蓋不掉,設計系統該怎麼處理?
思路
這是可覆蓋元件的必考題。根因是兩個 Tailwind utility(如 bg-blue-500 與 bg-red-500)特異性完全相同,誰贏純看在產出 CSS 裡誰排後面,與你在 className 字串寫的順序無關。所以直接把外部 class 拼在後面不保證覆蓋。設計系統的標配解法是 tailwind-merge:它懂 Tailwind 語意,會把衝突的 utility 去重、保留後傳入的。實務上會把它和 clsx 包成一個 cn() 工具,成為所有元件的共用底座。
示例
包一個 cn() 工具:
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
元件用 cn() 合併,外部 class 正確覆蓋:
function Button({ className, children }) {
return (
<button className={cn('bg-blue-500 px-4 py-2 rounded', className)}>
{children}
</button>
)
}
// cn('bg-blue-500', 'bg-red-500') → 'bg-red-500'(去重保留後者)
<Button className="bg-red-500">紅色按鈕</Button>
判準:能說「utility 特異性相同、勝負看產出順序,所以要用 tailwind-merge 去重」,就跟只會加 !important 的人拉開差距。 這也是 CVA + cn() 常一起出現的原因——CVA 管變體、cn() 讓變體可被外部覆蓋。
題目6:何時該用 @apply、何時用元件抽取、何時寫 Plugin?
思路
這題考的是抽象層次的決策,答錯很傷分(尤其在框架環境濫用 @apply)。核心原則是一條優先序:框架元件 > @apply > Plugin。有 React/Vue 等框架時,只要有樣式複用就優先抽成元件——因為元件能傳 props、能測試、能加互動邏輯,遠比 @apply 靈活;@apply 只該用在無法加 class 的場景,例如 Markdown 渲染出的 HTML、CMS 產生的內容;而 Plugin API 是最後手段,只在需要產生 Tailwind 沒有的 utility、或要跨專案共享時才用。
示例
決策樹:
有重複樣式要管理?
─────────────────────────────────────────
在框架專案(React/Vue)?
YES → 抽成元件(可傳 props、可測試) ← 首選
NO → 是框架/CMS 生成、無法加 class 的 HTML?
YES → @layer components 裡用 @apply
NO → 需要 Tailwind 沒有的 utility?
YES → Plugin API(可跨專案共享)
NO → @layer utilities 直接定義
─────────────────────────────────────────
原則:框架元件 > @apply > Plugin
@apply 的正確用途——渲染 Markdown 的內容區:
/* ✅ 無框架、無法在每個標籤加 class 的場景 */
@layer components {
.article-content h2 { @apply text-2xl font-semibold mt-10 mb-4; }
.article-content p { @apply text-gray-700 leading-relaxed mb-4; }
.article-content a { @apply text-blue-600 hover:text-blue-700 underline; }
}
判準:能點出「框架裡用 @apply 抽樣式是反模式,應優先抽元件」,就展現了對抽象層次的判斷力。
題目7:比較 shadcn/ui、Radix UI、Headless UI 與 MUI/Ant Design,你會怎麼選?
思路
這是元件庫選型題,答題主軸是「控制程度 vs 開發速度的光譜」。一端是完全掌控樣式的方案(Radix / Headless UI 只給行為邏輯、不給樣式;shadcn/ui 給行為 + 可直接改的基礎樣式),另一端是開箱即用但難客製的方案(MUI / Ant Design)。面試官不是要你背哪個好,而是要你根據情境給建議:重品牌設計、想完全掌控 → shadcn/Radix;後台系統、要快 → MUI/Ant。特別要能講清 shadcn/ui「複製原始碼到專案」而非 npm 依賴的模式差異。
示例
選型對照:
元件庫光譜(左=完全掌控樣式,右=開箱即用):
─────────────────────────────────────────
Radix UI / Headless UI → shadcn/ui → MUI / Ant Design
只給行為邏輯 行為+可改樣式 完整 UI,難客製
─────────────────────────────────────────
| 面向 | shadcn/ui | Radix UI | MUI / Ant Design |
|---|---|---|---|
| 樣式掌控 | 完全掌控 | 完全掌控 | 低(需覆蓋) |
| 安裝方式 | 複製原始碼進專案 | npm install | npm install |
| 客製難度 | 低(原始碼在手) | 中 | 高 |
| 設計一致性 | 自行維護 | 自行維護 | 內建 |
shadcn 的關鍵差異——元件是你的原始碼,不是黑箱依賴:
npx shadcn@latest add button dialog
# 產生 src/components/ui/button.tsx —— 你完全擁有、可直接改
選型建議:
shadcn/ui → 重品牌、有 Tailwind、React/Next
Radix UI → 需最細粒度控制、複雜無障礙需求
Headless UI → 想更輕量、需官方 Vue 支援
MUI/Ant → 後台系統、要大量現成元件、不在意客製
判準:能講清 shadcn「複製到專案」的優缺點,並依情境給建議,就贏過只會說「我都用 MUI」的人。
題目8:如何在大型團隊中強制執行設計一致性?
思路
這題的關鍵洞見是:一致性不能只靠人工 code review,要靠工具與流程自動化。答題分三個層面:型別約束(用 TypeScript 讓元件只接受設計系統定義的值,禁止任意 color: string)、Lint/格式化(ESLint 檢查、Prettier 自動排序 class)、CI 流程(把設計 Lint 與視覺回歸測試放進 pipeline)。再加上 Storybook 作為活的元件文件。面試官想聽你能不能把「一致性」從口號變成可自動檢查的機制。
示例
型別約束——只允許設計系統的值:
// ✅ 元件 props 只接受定義好的變體,不接受任意顏色
interface ButtonProps {
variant: 'primary' | 'secondary' | 'ghost' | 'destructive'
// 沒有 color?: string —— 從型別上就禁止亂用顏色
}
工具鏈——ESLint + Prettier 自動把關:
npm i -D eslint-plugin-tailwindcss prettier-plugin-tailwindcss
CI 流程——把檢查搬進 pipeline:
# .github/workflows/design-lint.yml
on: [pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx prettier --check "src/**/*.{tsx,jsx}" # class 排序
- run: npx eslint "src/**/*.{tsx,jsx}" # Tailwind 規則
- run: npx chromatic --exit-zero-on-changes # 視覺回歸(可選)
判準:能講出「型別 → Lint → CI → Storybook」這條自動化防線,而非只說『靠 review』,就是 Lead 該有的答案。
題目9:設計師與工程師如何交接?Figma Tokens 怎麼串進 Tailwind?
思路
這是跨職能協作題,考的是你懂不懂「讓 Figma 與程式碼指向同一份 token」。理想流程是:設計師在 Figma 用 Tokens 外掛(如 Tokens Studio)維護一份 token JSON,經由 CI/腳本把 JSON 轉成 CSS 變數(或 @theme 定義),工程師的程式碼只引用這些變數。這樣設計師改一個主色,經過管線就自動同步到程式碼,不用工程師手動抄色碼。面試官想聽你能不能描述這條「Figma → token JSON → 轉換 → @theme」的自動化交接鏈,以及它如何消除「設計稿與實作對不上」的老問題。
示例
設計師維護的 token JSON(Tokens Studio 匯出):
{
"color": {
"brand": { "primary": { "value": "#2563eb" }, "hover": { "value": "#1d4ed8" } }
},
"radius": { "md": { "value": "0.375rem" } }
}
用腳本把 JSON 轉成 v4 的 @theme(Style Dictionary 等工具可自動化):
// build-tokens.mjs(概念示意):JSON → CSS 變數
import tokens from './tokens.json' assert { type: 'json' }
const lines = ['@theme {']
lines.push(` --color-brand: ${tokens.color.brand.primary.value};`)
lines.push(` --color-brand-hover: ${tokens.color.brand.hover.value};`)
lines.push(` --radius-md: ${tokens.radius.md.value};`)
lines.push('}')
// 寫入 generated-tokens.css,由 app.css @import
工程師端只引用生成結果,永遠不手抄色碼:
@import "tailwindcss";
@import "./generated-tokens.css"; /* 由 Figma token 自動生成 */
判準:能描述「Figma → token JSON → 轉換腳本 → @theme」這條自動同步鏈,就展現了對設計↔工程交接的完整理解。
題目10:如何把大型的 CSS-in-JS 程式碼庫遷移到 TailwindCSS?
思路
這是架構師等級的遷移權衡題。核心觀念只有一句:別一次性重寫,要漸進遷移(Strangler Fig)。答題要能講出階段:先評估與建 token 對應表,再從葉子元件(無子依賴)開始一個一個換,每換一個就跑視覺回歸測試確保沒跑掉,最後才移除舊套件依賴。同時要點出共存期的風險:CSS 特異性衝突、動態樣式遺漏、bundle 暫時變大——並給出對策(設定 CSS Layer 順序、建動態 class 映射清單、設 bundle 警示)。這題考的就是「大規模變更要控制風險、可回退」的工程判斷。
示例
漸進遷移的階段:
遷移階段(Strangler Fig):
─────────────────────────────────────────
Phase 0 評估:盤點規模、建 token 對應表、設共存機制
Phase 1 Token 對齊:現有值 → @theme token
Phase 2 葉子元件:從無子依賴的元件開始,每個都做視覺測試
Phase 3 複合元件:處理動態樣式、Global Styles → @layer base
Phase 4 清理:移除 CSS-in-JS 依賴、確認 bundle 縮小
─────────────────────────────────────────
典型轉換——styled-components → Tailwind + CVA:
// 遷移後:把 props 驅動的樣式改成 CVA 變體
import { cva } from 'class-variance-authority'
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md font-medium transition-colors',
{
variants: {
variant: { primary: 'bg-blue-600 text-white hover:bg-blue-700', ghost: 'hover:bg-gray-100' },
size: { sm: 'px-3 py-1.5 text-sm', md: 'px-4 py-2 text-sm' },
},
defaultVariants: { variant: 'primary', size: 'md' },
}
)
共存期的風險與對策:
風險 對策
─────────────────────────────────────────
視覺回歸 每個元件遷移後跑 Chromatic/Percy
特異性衝突(新舊 CSS 並存) 設定 CSS Layer 順序,讓 Tailwind 優先
動態樣式遺漏 建動態 class 映射清單逐一審查
bundle 暫時變大 設 bundle 大小警示,確認最終更小
─────────────────────────────────────────
判準:能提「漸進遷移、從葉子元件開始、每步做視覺回歸」並講出共存風險與對策,就是架構師該有的遷移答案。
答題技巧與最佳實踐
設計題和其他面試題最大的差異:它沒有標準答案,只有權衡。把下面這套答題策略練熟,不管面試官丟什麼架構情境,你都能答得有條理、有深度。
第一步:先問需求,別急著給方案。 拿到「你會怎麼設計主題系統?」,先反問:「是一套品牌還是多品牌?需不需要執行時切換?暗色模式要不要?」——設計題最忌一聽到就開始寫 code。先釐清約束(一/多品牌、是否白牌、團隊規模、是否有既有系統),再給對應方案,這個「先問後答」的動作本身,就是資深工程師與新手的分水嶺。面試官往往刻意把題目講得模糊,就是要看你會不會問。
第二步:講方案時,一定要講權衡與代價。 「用 shadcn」不是答案,「用 shadcn,因為要重品牌客製、原始碼在手改起來快,代價是設計一致性要自己維護」才是。每個技術選擇都有代價,能主動講出代價,代表你真的用過、想過,而不是背了個名詞。@apply vs 元件抽取、多品牌拆檔 vs 覆蓋變數、自製 vs 用元件庫——每一組都要能說出「選 A 的代價是 B」。
第三步:用分層思維組織答案。 設計系統的所有問題,幾乎都能用「分層」回答:token 分原始/語義/元件三層、元件分基礎/複合/模式三層、抽象分元件/@apply/Plugin 三級。答題時先畫出層次,再說每層職責與單向依賴,面試官會立刻感受到你腦中有一張清楚的架構圖,而不是一堆零散的 class 知識。
第四步:把一致性講成「可自動檢查的機制」。 談團隊協作時,別停在「大家要遵守規範」這種口號。要能把一致性落地成型別約束、ESLint、Prettier、CI、Storybook 這些機器能檢查的機制——因為靠人一定會漏,靠工具才規模化。能把抽象的「一致性」變成具體的自動化防線,就是 Tech Lead 的思維高度。
收尾:每題釘一句判準。 「元件只碰語義 token」「切品牌只換值不換 class」「框架元件 > @apply > Plugin」「utility 特異性相同、勝負看產出順序」「別一次性重寫、漸進遷移」——一句能記住的判準,會讓面試官記住你這個答案,也讓你日後真的建設計系統時有現成的原則可依。
系列總結
這是 TailwindCSS 完整教學 系列的第五十篇,也是整個系列的最後一篇。上一篇《面試:除錯題》,我們練的是「線上出事怎麼查」的戰術能力;這一篇則把視野拉到最高,教你「如何用 Tailwind 撐起一整個產品的設計語言」——從 token 的三層分層、多品牌與白牌的主題策略、CVA 的元件變體抽象、抽象層次的取捨、跨團隊一致性的自動化約束、設計師與工程師的 Figma tokens 交接,到大型專案的漸進遷移。回顧本篇的核心:
- Token 分層:原始(調色盤)→ 語義(功能意義)→ 元件(細節),元件永遠只碰語義層;v4 的
@theme同時生成 utility 與可執行時覆蓋的 CSS 變數,是設計系統的骨架。 - 主題策略:多品牌/白牌靠
data-brand覆蓋語義變數,切品牌只換值不換 class,白牌則執行時注入;color-mix()可從單一主色推導衍生色。 - 元件抽象:CVA 管變體(
variants/compoundVariants/defaultVariants+ 型別安全)、cn()用tailwind-merge解覆蓋衝突;抽象層次遵循「框架元件 >@apply> Plugin」。 - 團隊協作:一致性靠「型別 → Lint → CI → Storybook」自動化,而非人工 review;設計交接靠「Figma → token JSON →
@theme」自動同步;遷移靠漸進的 Strangler Fig 加視覺回歸。
而這裡,也是整整 50 篇旅程的終點。回頭看這條學習路徑:我們從核心哲學(Utility-First、JIT/Oxide 引擎、class 掃描機制)出發,理解 Tailwind「為什麼這樣設計」;接著走過視覺工具(顏色、間距、字體、排版)與響應式(斷點、容器查詢、group/peer/has),把畫面刻得又快又準;再進到元件化(CVA、@apply、tailwind-merge、暗色模式)與生態系(shadcn、外掛、@theme 主題化),學會把零散的 class 組織成可維護的元件;然後在實戰中把知識綜合成真實專案;最後用面試四關(核心概念 → 技術題 → 除錯題 → 設計系統),把所學淬鍊成講得清楚、也用得出來的真本事。
從「會寫 class」到「能架構設計系統」,你已經走完了完整的一圈。但工具的真正價值,永遠在動手做——把這 50 篇裡任何一個打動你的技巧,今天就開一個專案親手試一次,你會發現讀懂和做出來之間,還有一段只能靠雙手跨過的距離。感謝你一路走到這裡,願 Tailwind 成為你打造美好介面時最順手的那把工具。我們,下一個系列再見。