軟體工程師的設計原則:完整指南
掌握視覺設計基礎以構建更好的介面。格式塔心理學、排版、色彩理論、間距系統、動畫原則,以及Dieter Rams等設計大師的教訓。包含16個優秀產品的案例研究。
title: “軟體工程師設計原則:完整指南” description: “掌握視覺設計基礎,打造更優秀的介面。Gestalt 心理學、字型排版、色彩理論、間距系統、動畫原則,以及來自 Dieter Rams 等設計大師的啟示。包含 16 款傑出產品的案例研究。” date: 2026-01-14 updated: 2026-01-17T13:30:00 author: Blake Crosley category: Design & Development tags: [Design, UI, UX, Typography, Color Theory, Gestalt, Animation, CSS, SwiftUI] url_slugs: - design-principles-software-engineers-complete-guide-2026 - visual-design-fundamentals-developers
軟體工程師的設計原則:完整指南
2026 年 1 月 17 日更新
2026 年 1 月更新: 本指南整合了經典設計原則與現代網頁及 iOS 開發的實作模式。內容涵蓋 Gestalt 心理學、字型排版系統、色彩理論、視覺層次、間距與動畫——以及 Dieter Rams 的設計哲學。請參閱設計研究深入了解 16 款傑出產品。
多年來,我在開發軟體的同時持續研究設計,從 Dieter Rams 等大師身上汲取原則,並深入分析 Linear、Stripe 和 Raycast 等產品的介面。本指南濃縮了這些理解,成為我當初開始關注軟體外觀與體驗時,希望能擁有的完整參考資料。
設計不是裝飾,而是溝通。每一個像素都在傳達功能、層次與意義。業餘軟體與專業軟體之間的差別,在於理解這些原則並一致地應用它們。
本指南假設你已經會寫程式。它教你如何「看」——理解為什麼有些介面感覺順暢自然,而有些卻顯得雜亂無章,更重要的是,教你如何打造前者。
目錄
第一部分:基礎
第二部分:設計哲學
第三部分:實作
第四部分:參考資料
Gestalt 心理學
「整體不同於部分的總和。」— Kurt Koffka
Gestalt 心理學於 1920 年代在德國發展,解釋人類如何感知視覺資訊。大腦不會看到個別的像素——它會將元素組織成有意義的模式。掌握這些原則,就能控制使用者如何感知你的介面。
接近性
相近的元素會被視為一個群組。
這是 UI 設計中最強大的 Gestalt 原則。空間比任何其他視覺屬性都更能傳達關聯性。
錯誤(等距 = 無群組):
┌─────────────────┐
│ Label │
│ │
│ Input Field │
│ │
│ Label │
│ │
│ Input Field │
└─────────────────┘
正確(不等距 = 清楚的群組):
┌─────────────────┐
│ Label │
│ Input Field │ ← 緊密(4px)- 相關
│ │
│ │ ← 寬鬆(24px)- 分隔群組
│ Label │
│ Input Field │ ← 緊密(4px)- 相關
└─────────────────┘
CSS 實作:
.form-group {
margin-bottom: 24px; /* Between groups: wide */
}
.form-group label {
margin-bottom: 4px; /* Label to input: tight */
display: block;
}
SwiftUI 實作:
VStack(alignment: .leading, spacing: 4) { // Tight within group
Text("Email")
.font(.caption)
.foregroundStyle(.secondary)
TextField("[email protected]", text: $email)
.textFieldStyle(.roundedBorder)
}
.padding(.bottom, 24) // Wide between groups
相似性
具有相同視覺特徵的元素會顯得相關。
當元素看起來相同時,使用者會假設它們的功能也相同。這就是為什麼設計系統會使用一致的按鈕樣式、卡片處理方式和字型排版。
導覽範例:
┌───────────────────────────────────┐
│ [Dashboard] [Projects] [Settings] │ ← 相同樣式 = 相同功能
│ │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │Card │ │Card │ │Card │ │ ← 相同樣式 = 相同內容類型
│ └─────┘ └─────┘ └─────┘ │
│ │
│ [+ New Project] │ ← 不同樣式 = 不同功能
└───────────────────────────────────┘
圖形-背景
內容應該與背景清楚分離。
大腦需要區分「圖形」(聚焦對象)與「背景」(底色)。不良的圖形-背景關係會造成視覺混淆。
技巧: - 對比(淺色圖形配深色背景,或反之) - 陰影(讓圖形浮於背景之上) - 邊框(界定圖形邊緣) - 模糊(模糊背景,銳化圖形)
/* Strong figure-ground relationship */
.card {
background: var(--color-surface); /* Figure */
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1); /* Elevation */
}
.modal-overlay {
background: rgba(0, 0, 0, 0.5); /* Dim ground */
backdrop-filter: blur(4px); /* Blur ground */
}
共同區域
在邊界內的元素會被視為群組。
將元素包圍在視覺容器中(卡片、方框、有邊框的區域)表示它們屬於同一群組。
連續性
眼睛會跟隨路徑、線條和曲線。
利用對齊和視覺流動來引導注意力穿越你的介面。
對齊中的連續性:
┌────────────────────────────────┐
│ Logo [Nav] [Nav] [Nav] │ ← 沿水平軸對齊
├────────────────────────────────┤
│ │
│ Headline │
│ ───────────────────────────── │ ← 眼睛跟隨左邊緣
│ Paragraph text continues │
│ along the same left edge │
│ │
│ [Primary Action] │ ← 仍在左邊緣
└────────────────────────────────┘
閉合性
大腦會補完不完整的形狀。
使用者不需要看到每個像素——他們會在腦中補完熟悉的形狀。這讓設計可以更加簡約優雅。
/* Horizontal scroll with partial card (closure) */
.card-carousel {
display: flex;
gap: 16px;
overflow-x: auto;
padding-right: 48px; /* Show partial card = scroll hint */
}
.card-carousel .card {
flex: 0 0 280px; /* Fixed width, partial visible */
}
Gestalt 快速參考
| 原則 | 規則 | 主要用途 |
|---|---|---|
| 接近性 | 相關 = 接近,無關 = 遠離 | 表單欄位、內容區塊 |
| 相似性 | 外觀相同 = 功能相同 | 按鈕、卡片、導覽 |
| 圖形-背景 | 清楚分離層次 | 卡片、對話框、覆蓋層 |
| 共同區域 | 邊界將內容群組化 | 設定區塊、使用者卡片 |
| 連續性 | 跟隨線條和對齊 | 時間軸、閱讀流動 |
| 閉合性 | 大腦補完形狀 | 圖示、捲動提示、骨架屏 |
字型排版
「字型排版是賦予人類語言持久視覺形式的工藝。」— Robert Bringhurst
字型排版是介面設計的基礎。文字傳達功能、層次和品牌。不良的字型排版讓介面更難使用;優秀的字型排版是隱形的——它就是能運作。
字級
一致的字級創造視覺和諧。使用數學比例。
1.25 倍率(建議用於 UI):
:root {
/* Base: 16px (1rem) */
--text-xs: 0.64rem; /* 10.24px - use sparingly */
--text-sm: 0.8rem; /* 12.8px - captions, labels */
--text-base: 1rem; /* 16px - body text */
--text-lg: 1.25rem; /* 20px - lead text */
--text-xl: 1.563rem; /* 25px - h4 */
--text-2xl: 1.953rem; /* 31.25px - h3 */
--text-3xl: 2.441rem; /* 39px - h2 */
--text-4xl: 3.052rem; /* 48.8px - h1 */
}
行高(Leading)
行高大幅影響可讀性。不同的內容需要不同的行高。
| 內容類型 | 行高 | 原因 |
|---|---|---|
| 標題 | 1.1 - 1.2 | 緊密、粗體、簡短 |
| UI 文字 | 1.3 - 1.4 | 標籤、按鈕 |
| 內文 | 1.5 - 1.7 | 可讀的段落 |
| 長篇內容 | 1.7 - 2.0 | 文章、文件 |
行寬(Measure)
最佳行寬可防止眼睛疲勞並提升閱讀理解力。
- 最佳: 每行 45-75 個字元
- 目標: 50-65 個字元
- 絕對上限: 85 個字元
p {
max-width: 65ch; /* ch unit = width of '0' character */
}
.article-body {
max-width: 70ch;
margin: 0 auto;
}
字型選擇
優先使用系統字型。 它們載入即時、符合平台風格,且針對螢幕最佳化。
:root {
--font-sans: system-ui, -apple-system, BlinkMacSystemFont,
'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
--font-mono: ui-monospace, 'SF Mono', 'Cascadia Code',
'JetBrains Mono', Consolas, monospace;
}
在以下情況使用自訂字型: - 品牌區隔(行銷網站) - 編輯/出版風格 - 系統字型無法達成的特定設計意圖
字重建立層次
使用字重來建立層次,不只是字級。
h1 { font-weight: 700; } /* Bold */
h2 { font-weight: 600; } /* Semibold */
h3 { font-weight: 600; } /* Semibold */
.lead { font-weight: 500; } /* Medium */
p { font-weight: 400; } /* Regular */
.meta { font-weight: 400; color: var(--text-muted); }
字型排版快速參考
| 屬性 | 內文 | 標題 | UI 標籤 |
|---|---|---|---|
| 字級 | 16-18px | 24-48px | 12-14px |
| 字重 | 400 | 600-700 | 500 |
| 行高 | 1.5-1.7 | 1.1-1.2 | 1.3-1.4 |
| 行寬 | 45-75ch | 不適用 | 不適用 |
| 對齊 | 靠左 | 置中可 | 靠左 |
色彩理論
「色彩是一種直接影響靈魂的力量。」— Wassily Kandinsky
色彩比文字傳達得更快。它建立情緒、引導注意力、傳遞意義,並建立品牌識別度。
60-30-10 法則
這是創造平衡介面最可靠的色彩分配方式。
┌──────────────────────────────────────────┐
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ 60% - 主色(背景)
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░│ 30% - 輔助色(卡片、區塊)
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░│
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓██████▓▓▓▓▓▓▓▓▓▓░░░░░░░░│ 10% - 強調色(按鈕、連結)
└──────────────────────────────────────────┘
建立色彩調色盤
每個介面都需要這些語意色彩:
:root {
/* Brand */
--color-primary: hsl(220, 80%, 50%);
--color-primary-hover: hsl(220, 80%, 45%);
/* Semantic */
--color-success: hsl(142, 76%, 36%); /* Green - positive */
--color-warning: hsl(38, 92%, 50%); /* Amber - caution */
--color-error: hsl(0, 84%, 60%); /* Red - danger */
/* Neutrals */
--color-background: hsl(0, 0%, 100%);
--color-surface: hsl(220, 14%, 96%);
--color-border: hsl(220, 13%, 91%);
/* Text */
--color-text: hsl(220, 13%, 13%);
--color-text-secondary: hsl(220, 9%, 46%);
--color-text-muted: hsl(220, 9%, 64%);
}
色彩心理學
| 色彩 | 心理效果 | UI 應用 |
|---|---|---|
| 藍色 | 信任、穩定、平靜 | 金融、科技、企業 |
| 綠色 | 成長、自然、成功 | 健康、環保、正向狀態 |
| 紅色 | 能量、緊迫、危險 | 警示、促銷、錯誤 |
| 橘色 | 溫暖、熱情 | CTA、活潑品牌 |
| 黃色 | 樂觀、警示 | 警告、強調 |
| 紫色 | 奢華、創意 | 高端產品 |
無障礙對比度
| 等級 | 一般文字 | 大型文字 | UI 元件 |
|---|---|---|---|
| AA | 4.5:1 | 3:1 | 3:1 |
| AAA | 7:1 | 4.5:1 | N/A |
工具: WebAIM Contrast Checker、Chrome DevTools 色彩選擇器
視覺層級
「設計是品牌的無聲大使。」— Paul Rand
視覺層級控制使用者首先、其次、再其次看到什麼。沒有清晰的層級,使用者必須費力尋找資訊。有了層級,介面讓人感覺毫不費力。
層級的六大工具
1. 大小 — 較大的元素首先吸引注意力
.hero-title { font-size: 3rem; } /* Dominant */
.section-title { font-size: 1.5rem; } /* Secondary */
.body-text { font-size: 1rem; } /* Baseline */
2. 字重 — 粗體突出,細體後退
h1 { font-weight: 700; }
.lead { font-weight: 500; }
p { font-weight: 400; }
3. 色彩與對比 — 高對比 = 吸引注意力
.title { color: var(--color-text); } /* Near black */
.meta { color: var(--color-text-muted); } /* Gray */
4. 位置 — 關鍵位置很重要
F 型模式(內容頁面): Z 型模式(登陸頁面):
████████████████████████ 1 ──────────────────► 2
████████ ↘
████ ↘
██ ↘
3 ──────────────────► 4
5. 留白 — 隔離創造重要性
.hero { padding: 120px 48px; } /* Generous space */
.data-table { padding: 12px; } /* Dense content */
6. 深度與層次 — 向前突出的元素吸引注意力
:root {
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
--shadow-md: 0 4px 6px rgba(0,0,0,0.1);
--shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
}
.card { box-shadow: var(--shadow-sm); }
.card:hover { box-shadow: var(--shadow-md); }
.modal { box-shadow: var(--shadow-lg); }
瞇眼測試
瞇著眼看你的設計。你還能看到層級嗎?如果可以,說明層級很強。
間距與節奏
「留白就像空氣:它是設計呼吸所必需的。」— Wojciech Zieliński
間距是設計的隱形結構。一致的間距創造視覺節奏——讓元素感覺彼此屬於一個連貫的系統。
8px 網格
8px 網格是業界標準,因為: - 可均勻分割(8、16、24、32、40、48…) - 適用於常見螢幕密度(1x、1.5x、2x、3x) - 無需計算即可創造一致節奏
:root {
--space-1: 4px; /* Tight: icon gaps */
--space-2: 8px; /* Compact: inline elements */
--space-3: 12px; /* Snug: form fields */
--space-4: 16px; /* Default: most gaps */
--space-6: 24px; /* Spacious: card padding */
--space-8: 32px; /* Section gaps */
--space-12: 48px; /* Major sections */
--space-16: 64px; /* Page sections */
--space-20: 80px; /* Hero spacing */
}
內部與外部間距
內部(padding): 元素內部的空間 外部(margin): 元素之間的空間
原則: 在相關群組內,內部間距通常應大於外部間距。
.card {
padding: 24px; /* Internal: spacious */
margin-bottom: 16px; /* External: less than padding */
}
元件間距模式
卡片:
.card { padding: 24px; border-radius: 12px; }
.card-header { margin-bottom: 16px; }
.card-title { margin-bottom: 4px; } /* Tight to subtitle */
按鈕:
.btn { padding: 12px 24px; border-radius: 8px; }
.btn--sm { padding: 8px 16px; }
.btn--lg { padding: 16px 32px; }
.btn-group { display: flex; gap: 12px; }
表單:
.form-row { margin-bottom: 24px; }
.form-label { margin-bottom: 4px; }
.form-help { margin-top: 4px; }
.form-actions { margin-top: 32px; display: flex; gap: 12px; }
間距快速參考
| 情境 | 建議間距 |
|---|---|
| 圖示到文字 | 4-8px |
| 標籤到輸入框 | 4px |
| 表單群組之間 | 24px |
| 卡片內距 | 20-24px |
| 卡片間距 | 16-24px |
| 區塊內距(行動裝置) | 48-64px |
| 區塊內距(桌面) | 80-96px |
| 按鈕內距(水平/垂直) | 24px / 12px |
動畫原則
「動畫不是讓圖畫動起來的藝術,而是繪製動作的藝術。」— Norman McLaren
動畫為介面注入生命。做得好,它引導注意力、傳達狀態、創造情感連結。做得差,它令人沮喪且分散注意力。
核心原則
動畫應該感覺是必然的,而不是裝飾性的。
好的動畫: 1. 傳達靜態設計無法表達的內容 2. 透過展示關係來降低認知負擔 3. 感覺自然且符合預期 4. 從有意識的感知中消失
差的動畫: 1. 僅因為「看起來很酷」而存在 2. 拖慢使用者 3. 讓人注意到它自身 4. 造成焦慮或不耐煩
UI 的關鍵原則
1. 預期 — 為使用者準備即將發生的事情。
.button {
transition: transform 0.1s ease-out;
}
.button:active {
transform: scale(0.97); /* Slight press before action */
}
2. 跟隨動作 — 讓動作以類似彈簧的方式自然完成。
.panel {
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
withAnimation(.spring(response: 0.4, dampingFraction: 0.7)) {
isOpen = true
}
3. 緩入緩出 — 自然界沒有任何東西以恆定速度移動。
| 曲線 | 使用時機 | 特性 |
|---|---|---|
ease-out |
進入的元素 | 快速開始,緩慢停止 |
ease-in |
退出的元素 | 緩慢開始,快速退出 |
ease-in-out |
狀態變化 | 全程平滑 |
linear |
載入指示器 | 連續、機械感 |
4. 舞台調度 — 將注意力引導到重要的地方。除非作為群組編排,否則一次只應有一個東西移動。
5. 交錯 — 元素應該依序到達,而不是同時出現。
.list-item {
animation: fadeSlideIn 0.3s ease-out both;
}
.list-item:nth-child(1) { animation-delay: 0ms; }
.list-item:nth-child(2) { animation-delay: 50ms; }
.list-item:nth-child(3) { animation-delay: 100ms; }
.list-item:nth-child(4) { animation-delay: 150ms; }
@keyframes fadeSlideIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
時間指南
| 持續時間 | 使用情境 | 感覺 |
|---|---|---|
| 50-100ms | 微互動(懸停、按壓) | 即時回饋 |
| 150-200ms | 簡單狀態變化(切換、選擇) | 輕快 |
| 250-350ms | 中等轉場(面板滑動、卡片翻轉) | 流暢 |
| 400-500ms | 大型動作(頁面轉場、模態框) | 從容 |
效能:黃金法則
只對 transform 和 opacity 進行動畫 — 這些是 GPU 加速的,不會觸發重排。
/* BAD: Animating layout */
.panel { transition: left 0.3s, width 0.3s; }
/* GOOD: Using transform */
.panel { transition: transform 0.3s; }
何時不使用動畫
-
使用者啟用了
prefers-reduced-motioncss @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } } -
動畫沒有傳達任何資訊 — 無謂的旋轉器、彈跳元素
- 使用者趕時間 — 錯誤狀態、表單驗證、搜尋結果
- 動畫會拖慢重複操作 — 快捷鍵應跳過動畫
動畫快速參考
:root {
/* Durations */
--duration-instant: 0.1s;
--duration-fast: 0.15s;
--duration-normal: 0.25s;
--duration-slow: 0.4s;
/* Easings */
--ease-out: cubic-bezier(0.0, 0.0, 0.58, 1.0);
--ease-in: cubic-bezier(0.42, 0.0, 1.0, 1.0);
--ease-in-out: cubic-bezier(0.42, 0.0, 0.58, 1.0);
--ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
}
Dieter Rams:十項原則
「少,但更好。」— Dieter Rams
Dieter Rams 是 20 世紀最具影響力的工業設計師。作為 Braun 從 1961 年至 1995 年的設計總監,他創造的產品在數十年後依然歷久彌新。他的作品直接啟發了 Apple 的設計語言。
好設計的十項原則
1. 好設計是創新的 不要複製。將進步的技術與創新設計結合。
2. 好設計使產品有用 每個元素都必須有目的。形式追隨功能。
3. 好設計是美的 美不是膚淺的——它是本質的。我們每天使用的產品影響著我們的幸福感。
4. 好設計使產品易於理解 使用者不應該需要說明書。介面自己教導自己。
5. 好設計是不引人注目的 設計應該支持,而不是壓倒一切。使用者的內容才是主角,而不是你的 UI。
/* Obtrusive: UI competes with content */
.editor {
background: linear-gradient(135deg, purple, blue);
border: 3px dashed gold;
}
/* Unobtrusive: UI recedes, content shines */
.editor {
background: var(--color-background);
border: 1px solid var(--color-border);
}
6. 好設計是誠實的 不要使用暗黑模式。不要過度承諾。對限制保持透明。
7. 好設計是持久的 避免會快速過時的潮流。經典優於時髦。
時髦的(會過時): 永恆的:
- 極端的玻璃擬態 - 乾淨的字體排版
- 霓虹色、故障效果 - 微妙的層次感
- 激進的漸層 - 中性調色盤搭配精心挑選的強調色
8. 好設計注重每一個細節 沒有任何東西是隨意的。載入狀態、空狀態、錯誤狀態——全都經過設計。
9. 好設計是環保的 效能就是環保。尊重使用者的注意力。高效的程式碼。
10. 好設計是盡可能少的設計 移除所有不必要的東西。最好的設計是隱形的。
2025 年網頁模式
現代網頁設計運用原生 CSS 功能,在許多情況下消除了對 JavaScript 的需求。
容器查詢
根據容器而非視窗大小來調整組件尺寸。
.card-grid {
container-type: inline-size;
container-name: card-grid;
}
.card {
display: grid;
gap: 16px;
padding: 20px;
}
@container card-grid (min-width: 400px) {
.card {
grid-template-columns: auto 1fr;
}
}
@container card-grid (min-width: 600px) {
.card {
padding: 32px;
gap: 24px;
}
}
:has() 選擇器
根據子元素選擇父元素——這在過去沒有 JavaScript 是不可能的。
/* Card with image gets different padding */
.card:has(img) {
padding: 0;
}
.card:has(img) .card-content {
padding: 20px;
}
/* Form group with error */
.form-group:has(.input:invalid) .form-label {
color: var(--color-error);
}
/* Highlight navigation when on that page */
.nav-item:has(a[aria-current="page"]) {
background: var(--color-surface);
}
CSS 巢狀結構
無需預處理器的原生巢狀寫法。
.card {
background: var(--color-surface);
border-radius: 12px;
padding: 24px;
& .card-title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 8px;
}
& .card-body {
color: var(--color-text-secondary);
line-height: 1.6;
}
&:hover {
box-shadow: var(--shadow-md);
}
@media (min-width: 768px) {
padding: 32px;
}
}
HTMX 整合
無需龐大 JavaScript 框架的伺服器驅動互動性。
<!-- Load content on click -->
<button hx-get="/api/more-items"
hx-target="#item-list"
hx-swap="beforeend"
hx-indicator="#loading">
Load More
</button>
<!-- Form with inline validation -->
<form hx-post="/api/contact"
hx-target="#form-response"
hx-swap="outerHTML">
<input type="email" name="email"
hx-post="/api/validate-email"
hx-trigger="blur"
hx-target="next .error" />
<span class="error"></span>
</form>
設計代符系統
一套完整的代符系統,確保應用程式的一致性。
:root {
/* Colors */
--color-text: #1a1a1a;
--color-text-secondary: #666666;
--color-text-muted: #999999;
--color-background: #ffffff;
--color-surface: #f8f9fa;
--color-surface-elevated: #ffffff;
--color-border: #e5e7eb;
--color-primary: #3b82f6;
--color-primary-hover: #2563eb;
--color-success: #10b981;
--color-warning: #f59e0b;
--color-error: #ef4444;
/* Typography */
--font-sans: system-ui, -apple-system, sans-serif;
--font-mono: "SF Mono", Consolas, monospace;
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 2rem;
--leading-tight: 1.25;
--leading-normal: 1.5;
--leading-relaxed: 1.75;
/* Spacing (8px base) */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
--space-12: 3rem; /* 48px */
--space-16: 4rem; /* 64px */
/* Borders */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-full: 9999px;
/* Shadows */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
/* Transitions */
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--duration-fast: 100ms;
--duration-normal: 200ms;
}
正確實現深色模式
不要只是反轉顏色——要為深色環境重新設計。
@media (prefers-color-scheme: dark) {
:root {
/* Neutrals */
--color-background: hsl(220, 13%, 10%);
--color-surface: hsl(220, 13%, 15%);
--color-surface-elevated: hsl(220, 13%, 18%);
--color-border: hsl(220, 13%, 23%);
/* Text (inverted) */
--color-text: hsl(220, 9%, 93%);
--color-text-secondary: hsl(220, 9%, 70%);
--color-text-muted: hsl(220, 9%, 55%);
/* Adjust saturation for dark mode */
--color-primary: hsl(220, 80%, 60%);
--color-success: hsl(142, 70%, 45%);
--color-error: hsl(0, 80%, 65%);
/* Shadows in dark mode need adjustment */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
}
}
深色模式原則: - 降低大面積區域的飽和度 - 提高強調色的亮度 - 加強陰影(需要更多對比度) - 刻意設計深色模式,而非事後補救
Figma 擷取工作流程
將設計檔案轉換為正式程式碼需要系統性地擷取設計代符——定義您設計語言的顏色、字型、間距和效果。
Figma 變數匯出
Figma 的原生變數功能提供最簡潔的擷取路徑:
匯出步驟:
1. 開啟 Figma 檔案 → 本地變數面板
2. 點擊集合選單 → “Export to JSON”
3. 儲存為 figma-variables.json
JSON 代符結構:
{
"colors": {
"primitive": {
"blue-500": { "value": "#3b82f6", "type": "color" },
"blue-600": { "value": "#2563eb", "type": "color" }
},
"semantic": {
"primary": { "value": "{colors.primitive.blue-500}", "type": "color" },
"primary-hover": { "value": "{colors.primitive.blue-600}", "type": "color" }
}
},
"spacing": {
"1": { "value": "4px", "type": "spacing" },
"2": { "value": "8px", "type": "spacing" },
"4": { "value": "16px", "type": "spacing" }
}
}
代符轉 CSS 轉換
CSS 自訂屬性:
:root {
/* Primitive colors (direct values) */
--color-blue-50: #eff6ff;
--color-blue-100: #dbeafe;
--color-blue-500: #3b82f6;
--color-blue-600: #2563eb;
--color-blue-900: #1e3a8a;
/* Semantic colors (reference primitives) */
--color-primary: var(--color-blue-500);
--color-primary-hover: var(--color-blue-600);
--color-background: var(--color-white);
--color-surface: var(--color-gray-50);
/* Spacing (8px grid) */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
/* Typography */
--font-size-sm: 0.875rem;
--font-size-base: 1rem;
--font-size-lg: 1.125rem;
--line-height-tight: 1.25;
--line-height-normal: 1.5;
/* Effects */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
}
深色模式代符:
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--color-gray-900);
--color-surface: var(--color-gray-800);
--color-text: var(--color-gray-100);
--color-text-secondary: var(--color-gray-400);
/* Adjusted shadows for dark mode */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
}
}
代符轉 SwiftUI 轉換
顏色擴展:
import SwiftUI
extension Color {
// MARK: - Primitive Colors
static let blue50 = Color(hex: "eff6ff")
static let blue500 = Color(hex: "3b82f6")
static let blue600 = Color(hex: "2563eb")
// MARK: - Semantic Colors
static let brandPrimary = Color.blue500
static let brandPrimaryHover = Color.blue600
// MARK: - Surface Colors
static let surfaceBackground = Color(light: .white, dark: Color(hex: "0f172a"))
static let surfaceElevated = Color(light: Color(hex: "f8fafc"), dark: Color(hex: "1e293b"))
}
extension Color {
init(hex: String) {
// Standard hex parsing implementation
}
init(light: Color, dark: Color) {
self.init(UIColor { traits in
traits.userInterfaceStyle == .dark ? UIColor(dark) : UIColor(light)
})
}
}
間距常數:
enum Spacing {
static let xs: CGFloat = 4 // --space-1
static let sm: CGFloat = 8 // --space-2
static let md: CGFloat = 16 // --space-4
static let lg: CGFloat = 24 // --space-6
static let xl: CGFloat = 32 // --space-8
}
// Usage
VStack(spacing: Spacing.md) {
// ...
}
.padding(Spacing.lg)
設計師交接清單
設計師應匯出的內容:
| 資源類型 | 格式 | 備註 |
|---|---|---|
| 顏色 | Variables JSON | 包含淺色 + 深色模式 |
| 字型 | Styles export | 字體、大小、字重、行高 |
| 間距 | Variables JSON | 記錄基礎單位 |
| 圖示 | SVG | 輪廓線、單色 |
| 圖片 | PNG @2x/@3x 或 WebP | 含壓縮 |
| 元件 | Figma 連結 | 供實作時參考 |
品質關卡標準:
- [ ] 所有顏色定義為變數(無硬編碼十六進位值)
- [ ] 字型使用已定義的文字樣式
- [ ] 間距遵循網格系統(8px 基礎)
- [ ] 提供深色模式變體
- [ ] 記錄互動狀態(懸停、活動、停用)
- [ ] 標註響應式斷點
- [ ] 註明無障礙需求(對比度)
開發人員收到的內容:
- 代符檔案(JSON/CSS/Swift 依平台而定)
- 含尺寸的元件規格
- 所需格式的資源匯出
- 互動文件(狀態、動畫)
- 無障礙標註
快速參考表
格式塔原則
| 原則 | 規則 | 用途 |
|---|---|---|
| 鄰近性 | 相關 = 靠近 | 表單、區塊 |
| 相似性 | 外觀相同 = 功能相同 | 按鈕、卡片 |
| 圖地關係 | 清晰的層次分離 | 對話框、卡片 |
| 連續性 | 跟隨線條 | 時間軸、對齊 |
| 封閉性 | 大腦會補全形狀 | 圖示、捲動提示 |
字型排版
| 元素 | 大小 | 字重 | 行高 |
|---|---|---|---|
| 內文 | 16px | 400 | 1.5-1.7 |
| 標題 | 24-48px | 600-700 | 1.1-1.2 |
| UI 標籤 | 12-14px | 500 | 1.3-1.4 |
| 說明文字 | 12px | 400 | 1.4 |
顏色角色
| 角色 | 淺色模式 | 深色模式 |
|---|---|---|
| 背景 | #ffffff | #0f172a |
| 表面 | #f4f5f7 | #1e293b |
| 邊框 | #e4e6ea | #334155 |
| 文字 | #1a1a2e | #f1f5f9 |
| 次要文字 | #6b7280 | #94a3b8 |
| 主色 | #3b82f6 | #60a5fa |
| 成功 | #22c55e | #4ade80 |
| 錯誤 | #ef4444 | #f87171 |
間距比例
| 代符 | 值 | 用途 |
|---|---|---|
| –space-1 | 4px | 圖示間距 |
| –space-2 | 8px | 行內元素 |
| –space-4 | 16px | 預設間距 |
| –space-6 | 24px | 卡片內距 |
| –space-8 | 32px | 區塊間距 |
| –space-16 | 64px | 頁面區塊 |
設計檢核表
在發布任何介面之前,請確認:
格式塔
- [ ] 相關元素比不相關元素更靠近(鄰近性)
- [ ] 相似功能有相似樣式(相似性)
- [ ] 前景和背景之間有清晰分離(圖地關係)
- [ ] 視線自然流過版面(連續性)
字型排版
- [ ] 基礎字體大小至少 16px
- [ ] 內文行高為 1.5 以上
- [ ] 每行字數低於 75 個字元
- [ ] 層次清晰(可區分 3 個層級)
- [ ] 全程使用一致的比例
顏色
- [ ] 所有文字通過 4.5:1 對比度(WCAG AA)
- [ ] 顏色不是唯一的指示方式(還有圖示/標籤)
- [ ] 深色模式經過刻意設計
- [ ] 遵循 60-30-10 分配原則
視覺層次
- [ ] 能辨識出最重要的第一元素
- [ ] 視線按預期順序流動
- [ ] 每個區塊有一個明確的行動呼籲
- [ ] 字型比例一致
間距
- [ ] 所有間距使用定義的比例(無隨意數值)
- [ ] 卡片/元件有一致的內距
- [ ] 行動裝置間距舒適
- [ ] 網格對齊一致(8px 基礎)
Dieter Rams 檢核
- [ ] 有任何東西可以移除嗎?
- [ ] 每個元素都有功能性目的嗎?
- [ ] 這在 5 年後會顯得過時嗎?
- [ ] 我設計了每個狀態嗎?
資源
書籍: - As Little Design as Possible by Sophie Lovell (Dieter Rams) - The Elements of Typographic Style by Robert Bringhurst
工具: - WebAIM Contrast Checker - Type Scale Generator - Figma Tokens Studio — 設計 token 管理
設計系統: - Apple HIG - Material Design 3 - Radix UI - shadcn/ui
設計研究
深入剖析 16 款傑出產品,記錄值得借鑑的設計模式與原則。
開發者工具
| 產品 | 關鍵貢獻 |
|---|---|
| Figma | 多人協作存在感、情境感知面板 |
| Warp | 區塊式終端機、CLI-GUI 橋接 |
| Framer | 視覺化響應式設計、屬性控制項 |
| Vercel | 深色模式典範、環境狀態指示 |
| Linear | 樂觀式 UI、鍵盤優先工作流程 |
| Raycast | 擴充系統、快速操作 |
iOS 原生應用(Apple Design Award 獲獎作品)
| 產品 | 關鍵貢獻 |
|---|---|
| Flighty | 15 種智慧狀態、Live Activities、資料視覺化 |
| Halide | 智慧啟動、手勢控制 |
| Bear | 字體排印優先、行內標籤 |
| Craft | 原生優先跨平台、巢狀頁面 |
| Things | 延遲日期、快速輸入模式 |
生產力與 AI
| 產品 | 關鍵貢獻 |
|---|---|
| Superhuman | 100ms 規則、命令面板訓練、練習式新手引導 |
| Perplexity | 引用優先 AI、串流階段 |
| Notion | 區塊系統、斜線指令 |
| Arc | 空間、分割視圖、命令列 |
| Stripe | 文件典範、API 設計 |
本指南透過實踐持續成長。設計原則是永恆的,但其應用會隨著技術與理解而演進。