色彩
以自適應角色建立介面色彩,結合圓角與陰影凸顯表面,並選擇明暗模式。
本頁目錄
#概覽
以角色建立介面色彩:表面、線條與文字的 class 在明暗模式中維持不變。當顏色本身就是重點,例如插圖或品牌點綴時,再選用色階。色彩變化應對應到角色、狀態,或讀者需要辨識的差異。
模式改變,角色不變
只需選擇一次角色。它的 light-dark() 值會跟隨元素配色方案,包括嵌在另一配色中的區域。
文字說明
- 保留角色. 兩個區域使用相同的表面、分隔線、強調文字與次要文字 class。
- 依區域解析. 角色值使用 light-dark()。每個區域的 color-scheme 會選擇明色或暗色,不需改變 class。
#選擇角色或色階
| 需求 | 使用 | 範例 |
|---|---|---|
| 頁面結構與文字層級 | 色彩角色 | bg-surface-raised, b-line-divider, fg-text-muted |
| 特定色彩 | 色階 | bg-blue-5, fg-blue-60 |
同一個版面,兩種模式
<section class="p-md r-lg b(1) b-solid b-line-divider bg-surface-raised fg-text-body"> <h2 class="m(0) text-lg font-regular fg-text-strong">Project updates</h2> <p class="mt-xs mb-md text-sm fg-text-muted">Three milestones changed this week.</p> <a class="fg-text-link underline" href="/updates">Continue</a></section>產生的 CSS
@layer theme { :root, :host { --color-zinc-40: oklch(68.6% .0028 265); --color-zinc-60: oklch(48.6% .003 265); --color-zinc-90: oklch(24.6% .0022 265) } :root, :host { --color-surface-raised: light-dark(var(--color-white), var(--color-zinc-90)); --color-line-divider: light-dark(oklch(0% 0 none / .12), oklch(100% 0 none / .12)); --color-text-muted: light-dark(var(--color-zinc-60), var(--color-zinc-40)) } :root, :host { --color-white: oklch(100% 0 none) }}@layer utilities { .bg-surface-raised { background-color: var(--color-surface-raised) } .b-line-divider { border-color: var(--color-line-divider) } .fg-text-muted { color: var(--color-text-muted) }}角色是色彩鍵名的一部分:bg-surface-raised 讀取 --color-surface-raised,b-line-divider 讀取 --color-line-divider。線條角色只設定顏色,因此邊框寬度與樣式須另外指定。色彩角色列出所有角色,調色盤則列出完整色階。
邊框色彩需要寬度與樣式搭配
所有方框起始皆為 border-style: none。範例的 border-box 尺寸相同,只改變所列邊框宣告。
文字說明
- b-line-divider 提供 border-color,b(2) 提供 border-width。兩者都不會改變 none 的邊框樣式。
- 加入 b-solid 後,2px 邊框才會畫出。邊框可沿用元件中其他已撰寫的必要條件,因此只看到色彩 class 時,請檢查完整樣式。
區分固定色階與語意角色
特定色彩使用色階;需要隨情境調整的決策則使用角色。
文字說明
兩條路徑分別呈現固定色階,以及選擇明暗值的角色。
#固定與自適應色相別名
fg-yellow 這類色相別名是固定色彩,在每個模式中都使用相同的值。fg-text-yellow 這類文字色相別名則會依模式選擇適合文字的前景色階。請在實際背景上檢查對比;自適應別名無法保證每種搭配都合適。
<svg class="fg-yellow" fill="currentColor" aria-hidden="true">…</svg><p class="fg-text-yellow">Pending review</p>產生的 CSS
@layer theme { :root, :host { --color-yellow-40: oklch(91.5% .1909 101.1); --color-yellow-90: oklch(52.17% .1199 62.2) } :root, :host { --color-yellow: var(--color-yellow-40); --color-text-yellow: light-dark(var(--color-yellow-90), var(--color-yellow-40)) }}@layer utilities { .fg-text-yellow { color: var(--color-text-yellow) } .fg-yellow { color: var(--color-yellow) }}彩色標籤使用文字色相別名;內文、強調文字與連結則使用文字角色。
#凸起表面
凸起表面結合表面角色、圓角 token 與陰影 token。可互動的表面在滑鼠移入或取得焦點時,將陰影提高一級。一般卡片與控制項使用小圓角;pill 留給刻意完全圓潤的形狀,例如下方徽章。
凸起表面
<a class="block p-md r-lg bg-surface-raised fg-text-body shadow-sm shadow-md:hover shadow-md:focus-visible" href="/notes"> <span class="flex items-center justify-between gap-sm"> <span class="fg-text-strong">Field notes</span> <span class="px-xs py-3xs pill bg-line-subtle text-xs fg-text-muted">12 new</span> </span></a>產生的 CSS
@layer theme { :root, :host { --radius-lg: .5rem } :root, :host { --shadow-sm: 0 0 0 1px light-dark(oklch(0% 0 none / .04), oklch(100% 0 none / .05)), 0 1px 1px -.5px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .3)), 0 2px 2px -1px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .26)), 0 4px 4px -2px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .24)); --shadow-md: 0 0 0 1px light-dark(oklch(0% 0 none / .05), oklch(100% 0 none / .06)), 0 1px 1px -.5px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .3)), 0 2px 2px -1px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .26)), 0 4px 4px -2px light-dark(oklch(0% 0 none / .04), oklch(0% 0 none / .24)), 0 8px 8px -4px light-dark(oklch(0% 0 none / .045), oklch(0% 0 none / .26)) }}@layer utilities { .r-lg { border-radius: var(--radius-lg) } .pill { border-radius: calc(infinity * 1px) } .shadow-sm { box-shadow: var(--shadow-sm) } .shadow-md\:hover:hover { box-shadow: var(--shadow-md) }}預設集的陰影以 light-dark() 設定顏色,因此 shadow-sm 保留幾何形狀,並跟隨元素的配色方案。pill 是固定 utility,不是圓角 token;寬高相等時會形成圓形。使用 rtl-lg、rtr-lg、rbl-lg 與 rbr-lg 可分別設定單一角落。各種尺度與自訂方式請見圓角與陰影。
相同 pill 圓角隨方框形狀調整
高度維持 64px。pill 提供圓角半徑,範例尺寸來自獨立的尺寸宣告。
文字說明
- pill 設定全圓角半徑,不設定寬度、高度或內距。
- 寬高相等時形成圓形。同高度但較寬的方框會形成膠囊,因此單靠 class 不保證圓形。
#明暗模式
預設集在根元素設定 color-scheme: light dark,角色與陰影則使用 light-dark(),因此頁面不需額外 class 就會跟隨系統偏好。若要指定模式,在根元素、巢狀區域或 Shadow Host 上設定 data-theme="light" 或 data-theme="dark":
一個 token,兩種區域配色
@theme { --color-surface-notes: light-dark(#f4f4f5, #27272a);}@layer base { [data-theme="light"] { color-scheme: light; } [data-theme="dark"] { color-scheme: dark; }}<section data-theme="dark" class="p-md r-lg bg-surface-notes fg-text-body wrap-anywhere"> <h2 class="m(0) text-lg font-regular">Dark notes</h2> <p class="mt-xs mb-md text-sm">This region chooses dark.</p> <article data-theme="light" class="p-md r-md bg-surface-notes fg-text-body"> <h3 class="m(0) text-md font-regular">A light region inside</h3> <p class="mt-xs mb(0) text-sm">The same surface token follows this article’s light scheme.</p> </article></section>產生的 CSS
@layer base { [data-theme="light"] { color-scheme: light; } [data-theme="dark"] { color-scheme: dark; }}@layer theme { :root, :host { --color-zinc-30: oklch(78% .0025 265); --color-zinc-70: oklch(39.8% .0028 265) } :root, :host { --color-text-body: light-dark(var(--color-zinc-70), var(--color-zinc-30)) } :root, :host { --font-weight-regular: 400; --font-size-sm: .875rem; --font-size-md: 1rem; --font-size-lg: 1.125rem; --text-sm: var(--font-size-sm); --text-sm--line-height: 1.5; --text-sm--letter-spacing: 0; --text-md: var(--font-size-md); --text-md--line-height: 1.6; --text-md--letter-spacing: 0; --text-lg: var(--font-size-lg); --text-lg--line-height: 1.5; --text-lg--letter-spacing: 0; --radius-md: .375rem; --radius-lg: .5rem; --spacing-xs: .5rem; --spacing-md: 1rem } :root, :host { --color-surface-notes: light-dark(#f4f4f5, #27272a) }}@layer utilities { .text-lg { font-size: var(--text-lg); line-height: var(--text-lg--line-height, normal); letter-spacing: var(--text-lg--letter-spacing, normal) } .text-md { font-size: var(--text-md); line-height: var(--text-md--line-height, normal); letter-spacing: var(--text-md--letter-spacing, normal) } .text-sm { font-size: var(--text-sm); line-height: var(--text-sm--line-height, normal); letter-spacing: var(--text-sm--letter-spacing, normal) } .bg-surface-notes { background-color: var(--color-surface-notes) } .r-lg { border-radius: var(--radius-lg) } .r-md { border-radius: var(--radius-md) } .fg-text-body { color: var(--color-text-body) } .font-regular { font-weight: var(--font-weight-regular) } .m\(0\) { margin: calc(0 * 1px) } .mb-md { margin-bottom: var(--spacing-md) } .mt-xs { margin-top: var(--spacing-xs) } .mb\(0\) { margin-bottom: calc(0 * 1px) } .wrap-anywhere { overflow-wrap: anywhere } .p-md { padding: var(--spacing-md) }}預設集已內建這兩個 data-theme 選擇器;範例 CSS 再次列出它們,以說明啟用方式。以 light-dark() 定義的自訂顏色也會以相同方式調整,切換模式不必重新編譯。巢狀區域會繼承父層 token,除非自行重新宣告;品牌主題應使用自己的選擇器,例如 [data-brand="ocean"],並在其中重新宣告角色 token。
@light 與 @dark 後綴是 prefers-color-scheme 媒體查詢。手動設定 data-theme 會改變 token,但不會啟用這些查詢。若 class 必須回應手動選擇,請宣告選擇器 mixin 並套用:
@mixin --manual-dark { &:where([data-theme="dark"], [data-theme="dark"] *) { @contents; }}<img class="(opacity:.85)@apply(--manual-dark)" src="/chart.png" alt="Weekly usage" />這個 mixin 檢查的是屬性,而不是實際使用的配色方案,因此巢狀的亮色區域內也會相符。優先使用自適應 token;作用範圍與解析方式請見變數與模式。
祖先選擇器可以進入淺色區域
虛線路徑追蹤明確的 dark 屬性。內層淺色邊界改變 color-scheme,不會改變選擇器檢查的祖先關係。
文字說明
- 本文的 --manual-dark mixin 比對 [data-theme="dark"] 本身或其後代元素。
- 巢狀 data-theme="light" 區域中的圖表,仍是外層 dark 區域的後代。因此即使 light-dark() 值使用本地淺色配置,它的不透明度包裝仍符合。
- 應跟隨實際採用色彩配置的值,請使用自適應 token;屬性選擇器只檢查其明確指定的關係。
最近的配色方案決定顏色
巢狀邊界代表 color-scheme。Token 名稱與標記維持不變。
文字說明
亮色文件包住一個暗色區域。同一個語意 token 在外側繪製亮色表面,在區域內繪製暗色表面。
#在實際情境中檢查角色
在兩種配色中檢查相同內容。確認強調與次要文字和實際表面的對比、連結的一般與焦點狀態,以及用來辨識控制項的邊界。色彩 token 提供一個值,本身不會建立對比、確保焦點可見,或賦予狀態意義。
選取項目或狀態應搭配標籤、圖示或其他可見提示,避免只靠顏色。巢狀區域須個別驗證:深色頁面中的手動亮色區域,仍需有適當且易讀的表面與前景搭配。











