如何建立動態且可設定的色彩配置,相關基礎概況
在這篇文章中,我想分享在 CSS 中管理多種色彩配置的方式。試用示範模式。
如果你偏好觀看影片,請參閱這篇文章的 YouTube 版本:
總覽
我們會利用自訂屬性和 calc()
建構無障礙顏色系統,配合使用者偏好設定自動調整網頁,同時盡量減少編寫體驗。我們從基本品牌顏色開始,並根據該顏色建立變化版本系統:2 種文字顏色、4 種表面顏色和相符的陰影。
本指南會先定義每個色彩配置的所有顏色。直到最後,他們才改變網頁。
品牌
通常品牌顏色已經確立,並以十六進位或 rgb 的形式提供。這項 GUI 挑戰的基本品牌顏色為 #0af
。首先,對於這個色彩系統,十六進位值需要轉換為 hsl。
* {
--brand: #0af;
--brand: hsl(200 100% 50%);
}
為了實現讓品牌顏色變暗或變亮 20% 的概念,hsl 顏色值的 3 個管道需要擷取至各自的自訂屬性,如下所示:
* {
--brand-hue: 200;
--brand-saturation: 100%;
--brand-lightness: 50%;
}
CSS 可針對這些顏色屬性執行數學運算,例如使用 calc(var(--brand-lightness) -
20%)
將亮度值降低 20%。這是建構色彩配置的基礎,因為 CSS 可以透過調整 hsl 飽和度和亮度值,讓所有顏色都維持在相同色調系列中。
淺色主題
每個顏色變化版本都會以相符的配置標示,在本例中,每個顏色變化版本都會加上 -light
。
品牌
從品牌顏色開始,透過在 hsl ()
函式括號內包裝 --brand-hue
、--brand-saturation
和 --brand-lightness
自訂屬性,即可重新建構品牌顏色,且不需進行任何計算:
* {
--brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
}
文字顏色
接下來,色彩配置的要素需要文字顏色。在淺色主題中,文字應為深色。請注意,下列顏色的亮度偏低,低於 50%。
* {
--text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
--text2-light: hsl(var(--brand-hue) 30% 30%);
}
--text1-light
,因為在亮度 10% 時非常昏暗,因此品牌色彩仍保有 100% 的飽和度,如此品牌顏色依然可以一眼穿過深色海軍。
--text2-light
,它不像第 1 種顏色一樣暗,但它是次要顏色,因此飽和度也較低。
表面顏色
表面顏色是指文字位於其上或內部的背景、邊框和其他裝飾性表面。在淺色主題中,這些是淺色主題,相對於深色文字顏色。如要使用 hsl 建立淺色,我們會在第三個亮度值中使用較高的百分比值。我們也會降低飽和度,讓淺灰色看起來不會太偏色。
* {
--surface1-light: hsl(var(--brand-hue) 25% 90%);
--surface2-light: hsl(var(--brand-hue) 20% 99%);
--surface3-light: hsl(var(--brand-hue) 20% 92%);
--surface4-light: hsl(var(--brand-hue) 20% 85%);
}
我們建立了 4 個表面顏色,因為裝飾顏色通常需要更多的變化版本,用於互動時刻 (例如 :focus
或 :hover
),或是建立紙層外觀。在這些情況下,建議將 --surface2-light
的滑鼠游標轉換為 --surface3-light
,這樣一來,滑鼠游標會提高對比度 (亮度為 99% 至 92%,使畫面變暗)。
陰影
色彩配置中的陰影效果雖然超越現實,但可為效果增添真實感,並有助於與不切實際的黑色陰影效果區隔開來。為此,陰影的顏色會使用色調自訂屬性,並以略微飽和的色調呈現,但仍非常深色。基本上是建立非常暗的略帶藍色的陰影。
* {
--surface-shadow-light: var(--brand-hue) 10% 20%;
--shadow-strength-light: .02;
}
--surface-shadow-light
並未包裝在 hsl 函式中。這是因為 --shadow-strength
值會組合起來產生某些不透明度,而 CSS 需要這些片段才能執行計算。如要瞭解詳情,請跳至「陰影」一節。
所有淺色調
您無須在 CSS 中在單一位置搜尋所有光源顏色的製作方式。
* {
--brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
--text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
--text2-light: hsl(var(--brand-hue) 30% 30%);
--surface1-light: hsl(var(--brand-hue) 25% 90%);
--surface2-light: hsl(var(--brand-hue) 20% 99%);
--surface3-light: hsl(var(--brand-hue) 20% 92%);
--surface4-light: hsl(var(--brand-hue) 20% 85%);
--surface-shadow-light: var(--brand-hue) 10% calc(var(--brand-lightness) / 5);
--shadow-strength-light: .02;
}
深色主題
大多數品牌的名稱並非以深色主題開頭,而是以淺色為主的變體主題。另一方面,使用者通常會在不同情境 (例如夜間) 選擇深色主題。這些因素促使我記住深色主題的兩件事:
- 使用者通常會在黑暗環境下使用這個主題,因此請在黑暗環境下進行測試。
- 顏色應去飽和,以免因過於濃烈而產生螢幕抖動。
品牌
淺色主題使用 3 個品牌 hsl 色彩管道值,且未更改,深色主題則不會。飽和度減半,亮度相對減少 50%。
* {
--brand-dark: hsl(
var(--brand-hue)
calc(var(--brand-saturation) / 2)
calc(var(--brand-lightness) / 1.5)
);
}
文字顏色
在深色主題中,文字顏色應為淺色。以下顏色的亮度值較高,因此較接近白色。
* {
--text1-dark: hsl(var(--brand-hue) 15% 85%);
--text2-dark: hsl(var(--brand-hue) 5% 65%);
}
表面顏色
在深色主題中,途徑顏色應為深色。下列顏色亮度和飽和度偏低,第 1 個表面最暗,亮度為 10%。
* {
--surface1-dark: hsl(var(--brand-hue) 10% 10%);
--surface2-dark: hsl(var(--brand-hue) 10% 15%);
--surface3-dark: hsl(var(--brand-hue) 5% 20%);
--surface4-dark: hsl(var(--brand-hue) 5% 25%);
}
陰影
在深色主題中,陰影非常難以察覺。這很合理,因為要讓已經相當暗的內容變得更暗,難度相當高。這時 --shadow-strength-dark
就非常實用,因為我們可以透過變更一個變數來使陰影變暗。
* {
--surface-shadow-dark: var(--brand-hue) 50% 3%;
--shadow-strength-dark: .8;
}
另外,請注意陰影的飽和度。您在查看介面時,是否能注意到顏色?請嘗試從 devtools 中移除飽和度,你比較喜歡哪一個?
所有深色
* {
--brand-dark: hsl(var(--brand-hue) calc(var(--brand-saturation) / 2) calc(var(--brand-lightness) / 1.5));
--text1-dark: hsl(var(--brand-hue) 15% 85%);
--text2-dark: hsl(var(--brand-hue) 5% 65%);
--surface1-dark: hsl(var(--brand-hue) 10% 10%);
--surface2-dark: hsl(var(--brand-hue) 10% 15%);
--surface3-dark: hsl(var(--brand-hue) 5% 20%);
--surface4-dark: hsl(var(--brand-hue) 5% 25%);
--surface-shadow-dark: var(--brand-hue) 50% 3%;
--shadow-strength-dark: .8;
}
昏暗主題
這個色彩配置主要用於調配亮度和飽和度。系統應具備足夠的飽和度,才能仍能顯示色調,但也應該僅傳遞對比分數,因為本來就會比較暗,對比度也較低。
品牌
* {
--brand-dim: hsl(
var(--brand-hue)
calc(var(--brand-saturation) / 1.25)
calc(var(--brand-lightness) / 1.25)
);
}
文字顏色
* {
--text1-dim: hsl(var(--brand-hue) 15% 75%);
--text2-dim: hsl(var(--brand-hue) 10% 61%);
}
表面顏色
* {
--surface1-dim: hsl(var(--brand-hue) 10% 20%);
--surface2-dim: hsl(var(--brand-hue) 10% 25%);
--surface3-dim: hsl(var(--brand-hue) 5% 30%);
--surface4-dim: hsl(var(--brand-hue) 5% 35%);
}
陰影
* {
--surface-shadow-dim: var(--brand-hue) 30% 13%;
--shadow-strength-dim: .2;
}
將所有顏色調暗
* {
--brand-dim: hsl(var(--brand-hue) calc(var(--brand-saturation) / 1.25) calc(var(--brand-lightness) / 1.25));
--text1-dim: hsl(var(--brand-hue) 15% 75%);
--text2-dim: hsl(var(--brand-hue) 10% 61%);
--surface1-dim: hsl(var(--brand-hue) 10% 20%);
--surface2-dim: hsl(var(--brand-hue) 10% 25%);
--surface3-dim: hsl(var(--brand-hue) 5% 30%);
--surface4-dim: hsl(var(--brand-hue) 5% 35%);
--surface-shadow-dim: var(--brand-hue) 30% 13%;
--shadow-strength-dim: .2;
}
無障礙顏色
請注意,深色文字顏色組合中亮度最低的為 65%,深色表面中亮度最高的為 25%。也就是說,兩者之間的亮度呼吸空間為 40%。在淺色主題中,空白區域占 55%。將文字和表面顏色之間的亮度差異保持在約 40-50% 左右,有助於維持較高的色彩對比度,同時也可在分數不佳時調整細微的調整工具。
我稱之為「碰碰到燈塔」,也就是在工具顯示我通過之前,將亮度值往來的互動。
本挑戰建立的每個主題都通過對比分數。暗色系色彩配置的對比度最低,但仍符合最低要求。為協助團隊中的其他成員使用良好的對比色彩,建議您建立類別名稱,將表面顏色與無障礙文字顏色配對。
.surface1 {
background-color: var(--surface1);
color: var(--text2);
}
.surface2 {
background-color: var(--surface2);
color: var(--text2);
}
.surface3 {
background-color: var(--surface3);
color: var(--text1);
}
.surface4 {
background-color: var(--surface4);
color: var(--text1);
}
雷達陰影
主題會使用名為 .rad-shadow
的公用程式類別。這個陰影是由這項光滑陰影工具產生,非常感謝。我使用產生的程式碼片段,並運用自己的顏色和不透明度計算方式進行自訂。這是為了建立陰影,讓我可以在每個色彩配置中調整陰影。
為達成這個目標,我為每個色彩配置建立了 2 個變數,分別是陰影顏色和陰影強度。顏色用於調整飽和度和暗度,而強度則可在使用深色色彩配置時,輕鬆提高陰影強度。最終結果如下所示。
:root {
--surface-shadow-light: var(--brand-hue) 10% 20%;
--shadow-strength-light: .02;
}
.rad-shadow {
box-shadow:
0 2.8px 2.2px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
0 6.7px 5.3px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .01)),
0 12.5px 10px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
0 22.3px 17.9px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
0 41.8px 33.4px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
0 100px 80px hsl(var(--surface-shadow) / var(--shadow-strength))
;
}
如果我要進一步在色彩配置中加入陰影,也會將陰影角度設為設計符號常數,因為設計中的所有陰影之間的光線方向應相同。
使用色彩配置
預先定義顏色完成後,現在是時候將這些顏色轉換為不受配色方案影響的屬性。我的意思是,身為這個色彩配置專案中的 CSS 作者,您幾乎不需要存取特定色彩配置的值。我希望讓使用者能輕鬆遵守主題。
為達成這個目的,您應只透過通用自訂屬性使用色彩配置,我們稍後會定義這些屬性。如此一來,使用設計變數的使用者就不需要擔心目前設定的是哪種色彩配置,只需使用表面和文字顏色即可。請改用 color: var(--text1)
取代 color: var(--text1-light)
。所有顏色的調整和轉換作業都是在 CSS 中較高層級完成。
深入瞭解下列程式碼區塊中的淺色主題連接樣式,將一般自訂屬性連結至淺色主題專屬顏色。如今,所有 var(--brand)
的用途都會使用淺色品牌顏色。
淺色主題 (自動)
:root {
color-scheme: light;
--brand: var(--brand-light);
--text1: var(--text1-light);
--text2: var(--text2-light);
--surface1: var(--surface1-light);
--surface2: var(--surface2-light);
--surface3: var(--surface3-light);
--surface4: var(--surface4-light);
--surface-shadow: var(--surface-shadow-light);
--shadow-strength: var(--shadow-strength-light);
}
網站現在使用淺色主題。這是非常有趣的成功時刻!繼續在其他色彩配置環境中使用預先定義的色彩,之後再運用這些重要時刻。
深色主題 (自動)
@media (prefers-color-scheme: dark) {
:root {
color-scheme: dark;
--brand: var(--brand-dark);
--text1: var(--text1-dark);
--text2: var(--text2-dark);
--surface1: var(--surface1-dark);
--surface2: var(--surface2-dark);
--surface3: var(--surface3-dark);
--surface4: var(--surface4-dark);
--surface-shadow: var(--surface-shadow-dark);
--shadow-strength: var(--shadow-strength-dark);
}
}
淺色主題
[color-scheme="light"] {
color-scheme: light;
--brand: var(--brand-light);
--text1: var(--text1-light);
--text2: var(--text2-light);
--surface1: var(--surface1-light);
--surface2: var(--surface2-light);
--surface3: var(--surface3-light);
--surface4: var(--surface4-light);
--surface-shadow: var(--surface-shadow-light);
--shadow-strength: var(--shadow-strength-light);
}
深色主題
[color-scheme="dark"] {
color-scheme: dark;
--brand: var(--brand-dark);
--text1: var(--text1-dark);
--text2: var(--text2-dark);
--surface1: var(--surface1-dark);
--surface2: var(--surface2-dark);
--surface3: var(--surface3-dark);
--surface4: var(--surface4-dark);
--surface-shadow: var(--surface-shadow-dark);
--shadow-strength: var(--shadow-strength-dark);
}
昏暗主題
[color-scheme="dim"] {
color-scheme: dark;
--brand: var(--brand-dim);
--text1: var(--text1-dim);
--text2: var(--text2-dim);
--surface1: var(--surface1-dim);
--surface2: var(--surface2-dim);
--surface3: var(--surface3-dim);
--surface4: var(--surface4-dim);
--surface-shadow: var(--surface-shadow-dim);
--shadow-strength: var(--shadow-strength-dim);
}
此時,作者可以視需要自由使用提供的色彩配置泛型,且不必再擔心主題。
結論
既然你知道我如何做到,你會怎麼做呢?🙂
讓我們多方嘗試,瞭解在網路上建構應用程式的所有方式。建立 Codepen 或主持自己的示範,並透過 Twitter 推文寄給我,我會將其新增至下方的社群重混作品部分。
來源
社群重混版本 - @chris-kruining 為 no-preference
、more
和 less
新增了色相滑桿、狀態顏色和對比模式:示範。