高級液態玻璃
目標:打造一種感覺平靜、有空間感且高級的介面。玻璃是一種用於浮動於內容之上的控制元件的材質。它不應是一種到處濺灑的風格。成功測試:用戶會說「這感覺很乾淨而且有層次感」,而不是「有人把一切東西都加了模糊效果」。
此技能控制Android (Compose)、iOS (SwiftUI)、Flutter 與 Web (CSS / Tailwind) 平台上的材質、層級結構、深度、動態與無障礙性。專案本身的品牌負責控制品牌識別、調色盤與文案。預設品牌代碼位於 assets/tokens.json。
0. 安全與範圍
- 僅在用戶選定的專案內工作。請勿讀取機密、金鑰或環境變數。請勿發起網路請求或安裝套件;如果需要某個函式庫,請直接命名並讓用戶決定。
- 在修改現有應用程式程式碼之前,先提出變更建議。
- 僅使用虛構的範例內容。
- 在非 Apple 平台上,絕對不要使用 Apple 字體 (San Francisco) 或 SF Symbols。請使用 Inter、Roboto 或平台適用的字體,搭配 Material Symbols / Lucide 風格圖示。在 iOS (SwiftUI) 上,使用原生的 SF Symbols 與系統字體是標準做法。
- 標記為 (VERIFY) 的事實可能會隨著 API 版本過時;請務必根據專案相依性進行確認。
1. 五大硬性規則
- 內容永不使用玻璃。卡片、列表行、表單、頁面背景與媒體應保持不透明或柔和的表面。
- 玻璃僅用於浮動層:底部導航藥丸、可滾動內容上方的頂部欄、浮動操作按鈕、底部面板與選單、搜尋欄、提示/輕食條、以及小型浮動標籤。
- 不在玻璃上疊加玻璃。在玻璃表面內部,使用實色填充、細微分隔線或不透明度的差異來分隔項目。
- 可讀性優於美觀。內文文字必須在最差背景情況下達到 4.5:1 的對比度(大字型與圖示為 3:1)。請執行
scripts/contrast_check.py。 - 每個玻璃表面都有實心備援(適用於較舊的 OS 版本、「減少透明度」無障礙設定、省電模式、低 GPU 容量,或缺乏
backdrop-filter的瀏覽器)。
在將玻璃應用於任何元素之前的把關問題:「這個材質傳達了什麼功能性角色?」 有效答案:它浮動於滾動內容之上;它是臨時性或上下文相關的;它必須在內容於其下方移動時保持可觸及。沒有答案 = 不使用玻璃。
2. 通用工作流程
- 檢查:目標平台 (Android Compose, iOS SwiftUI, Flutter, Web)、OS 版本限制、現有主題代碼、導航結構、無障礙需求與效能目標。
- 圖層地圖 (在撰寫任何程式碼之前):建立元素 -> 圖層 (內容 / 結構 / 浮動) -> 是否使用玻璃 -> 層級 -> 原因 的表格。連同計畫一起呈現。
- 代碼:從
assets/tokens.json開始;調整品牌顏色;對每個層級在兩種模式(深色/淺色)下重新執行python scripts/contrast_check.py --tokens assets/tokens.json。 - 使用平台範本建構:
- Android:
assets/GlassTheme.kt與references/compose-implementation.md - iOS (SwiftUI):
assets/GlassView.swift與references/swiftui-implementation.md - Flutter:
assets/glass_theme.dart與references/flutter-implementation.md - Web (CSS / Tailwind):
assets/glass.css、assets/tailwind-glass.config.js與references/web-implementation.md
- Android:
- 驗證:使用
references/review-checklist.md和scripts/audit_compose.py(Android) 進行檢查。報告證據(對比度數值、每個畫面的玻璃層數量、備援渲染結果)。
3. 材質層級(起始值)
| 層級 | 用途 | 模糊 | 填充 (深色模式) | 填充 (淺色模式) |
|---|---|---|---|---|
| 無 | 內容、卡片、列表、背景 | - | 不透明表面 | 不透明表面 |
| 薄 (thin) | 僅圖示或大標籤控制元件、標籤 | 16 dp/px | 墨水色 @ 0.55 | 白色 @ 0.55 |
| 一般 (regular) | 導航藥丸、頂部欄、搜尋欄、FAB、提示 | 24 dp/px | 墨水色 @ 0.66 | 白色 @ 0.70 |
| 厚 (thick) | 面板、選單、對話框、文字量大的覆蓋層 | 32 dp/px | 墨水色 @ 0.78 | 白色 @ 0.82 |
| 遮罩 (scrim) | 模態面板後方的調暗層 | 0-8 dp/px | 黑色 @ 0.20-0.45 | 黑色 @ 0.20-0.45 |
詳細資訊與驗證後的對比度數值:references/tokens.md。填充顏色會混入表面的墨水色,而非純白色,這樣深色模式下的文字就能在明亮的背景上維持可讀性。
4. 平台實戰檢查
Android (Jetpack Compose)
Modifier.blur()或RenderEffect模糊的是元素本身的內容,而非其後方的內容。真正的背景模糊需要一個函式庫(Haze 使用 Apache-2.0 授權,支援 Compose),或針對對話框使用視窗模糊(API 31+)。- 模糊效果需要 Android 12 (API 31) 或更高版本 (VERIFY)。低於 API 31 時,一律渲染實心備援表面。
- 預算:每個畫面最多 2-3 個同時存在的模糊圖層。絕不模糊列表項目。
- 完整細節:
references/compose-implementation.md。
iOS (SwiftUI)
- 使用原生 SwiftUI 材質:
.ultraThinMaterial(薄層級)、.thinMaterial/.regularMaterial(一般層級)、以及.thickMaterial(厚層級)。 - 使用
RoundedRectangle(cornerRadius: ..., style: .continuous)支援 iOS 連續圓角。 - 使用
.presentationBackground(.thinMaterial)為底部面板添加背景材質(iOS 16.4+)。 - 完整細節:
references/swiftui-implementation.md。
Flutter
- 使用
BackdropFilter搭配ImageFilter.blur(sigmaX: tier.blur, sigmaY: tier.blur),並以ClipRRect包裹。 - 務必使用
RepaintBoundary包裹,以防止背景模糊在每一幀都重新繪製。 - 絕對不要在
ListView.builder或GridView.builder項目內部使用BackdropFilter。 - 完整細節:
references/flutter-implementation.md。
Web (CSS / Tailwind CSS)
- 務必同時包含
-webkit-backdrop-filter: blur(...)和backdrop-filter: blur(...)以確保跨瀏覽器支援(Safari 需要-webkit-)。 - 務必為較舊的瀏覽器指定一個
@supports not (backdrop-filter: blur(1px))備援方案。 - 務必實作
@media (prefers-reduced-transparency: reduce)備援方案,以使用實色背景。 - 完整細節:
references/web-implementation.md。
5. 無障礙模式(全部實作)
- 減少透明度:檢查系統無障礙標誌(Web 上的
prefers-reduced-transparency、SwiftUI 中的accessibilityReduceTransparency、Flutter 中的accessibleNavigation,或在 Android 上使用應用程式內切換)。將玻璃表面替換為帶有可見 1 dp/px 邊框的實心表面代碼。 - 大字型 (200%) 與螢幕閱讀器:資訊不可僅透過顏色傳達;為僅圖示的控制元件加上標籤;邏輯的焦點順序。
- 減少動態效果:將彈簧動畫取代為快速淡入淡出 (150 毫秒);保留狀態回饋。
- 觸控目標:最小 48x48 dp / 44x44 pt。手勢操作(滑動)務必提供按鈕或可存取的選單替代方案。
6. 元件與幾何
導航藥丸、頂部欄、FAB、面板、搜尋欄、標籤、卡片與分流堆疊的規格:references/components.md。
使用一致的圓角半徑:
- 小型標籤:999 (全藥丸)
- 小型控制元件 / 按鈕:16 dp/pt
- 內容卡片(不透明):24 dp/pt
- 浮動導航藥丸:28 dp/pt
- 模態面板:32 dp/pt
- 巢狀元素的半徑 = 外層半徑 - 內邊距。
7. 動態與觸覺回饋
彈簧動畫 (250-350 毫秒持續時間)、短暫淡入淡出 (150 毫秒)、最小或零反彈超調。在閾值觸發點(滑動確認、藥丸選擇)提供細微的觸覺震動。按下狀態:縮放 0.97 並加上柔和的高光。尊重系統的減少動態效果設定。
8. 圖片提示模式(參考畫面)
在生成 UI 模擬圖提示時,請遵循 references/image-prompts.md:每個提示只生成一個畫面、自包含的樣式區塊、精確的螢幕文字、玻璃僅用於浮動層、「卡片為不透明」、符合平台規範的狀態列。將輸出用作佈局與氛圍參考,然後使用設計代碼在程式碼中實作。
9. 審查模式
當被要求審查設計或程式碼庫時:
- 將每個 UI 元素分類到其圖層(內容 vs. 浮動)。
- 計算每個畫面的玻璃圖層數量(強制執行最多 2-3 層的預算)。
- 掃描反模式(卡片上的玻璃、玻璃內嵌套玻璃、缺少備援)。
- 執行對比度驗證(
python scripts/contrast_check.py --tokens assets/tokens.json)。 - 對 Android 專案,執行
python scripts/audit_compose.py <src>。 - 根據嚴重程度列出發現,並參考
references/review-checklist.md提供修正指導。
10. 參考資料與檔案
references/principles.md- 核心空間原則與 Apple 設計靈感references/tokens.md- 代碼表、顏色值與驗證後的對比度數值references/compose-implementation.md- Android Compose 架構與程式碼片段references/swiftui-implementation.md- iOS SwiftUI 架構與程式碼片段references/flutter-implementation.md- Flutter 架構與程式碼片段references/web-implementation.md- Web CSS 與 Tailwind CSS 架構與程式碼片段references/components.md- 元件幾何、佈局與狀態references/image-prompts.md- 用於 AI 模型生成模擬圖的提示範本references/review-checklist.md- 品質檢查點與反模式scripts/contrast_check.py- WCAG 對比度驗證腳本scripts/audit_compose.py- Compose 靜態掃描器腳本assets/tokens.json- 完整的設計代碼結構assets/GlassTheme.kt- Jetpack Compose 範本assets/GlassView.swift- SwiftUI 範本assets/glass_theme.dart- Flutter 範本assets/glass.css與assets/tailwind-glass.config.js- Web CSS 與 Tailwind 範本