建立色彩配置

如何建立動態及可設定的色彩配置的基本總覽

在本文中,我想分享在 CSS 中管理多種色彩配置的方式。立即試用

示範

如果你偏好使用影片,也可以觀看這篇 YouTube 文章:

總覽

我們會使用自訂屬性和 calc() 建構無障礙色彩系統,依使用者偏好調整網頁,同時維持網頁編寫體驗。首先,我們從基本品牌顏色著手,建構一個包含變化版本的系統:2 種文字顏色、4 種介面顏色和相符的陰影。

本指南會先說明如何預先定義每種色彩配置的所有顏色。直到最末端才用來變更頁面。

The Brand

通常已經建立品牌顏色,並以 16 進位rgb 的形式提供。這項 GUI 挑戰的基本品牌顏色為 #0af。首先,針對這個顏色系統,十六進位值需要轉換為 hsl

* {
  --brand: #0af;
  --brand: hsl(200 100% 50%);
}

為了讓品牌顏色變暗或調亮品牌顏色,假設 20%,Hsl 顏色值的 3 個管道必須擷取到專屬的自訂屬性中,如下所示:

* {
  --brand-hue: 200;
  --brand-saturation: 100%;
  --brand-lightness: 50%;
}

CSS 可以對這些色彩屬性進行數學運算,例如將亮度值減少 20%。calc(var(--brand-lightness) - 20%)此為建構色彩配置的基礎,因為 CSS 可透過調整 hsl 飽和度和亮度數量,讓所有顏色保持一致。

淺色主題

每個顏色變化版本都會以相符的配置標示。在本例中,每個顏色變化版本都會附加 -light

淺色主題結束結果預覽畫面

Brand

從品牌顏色開始,這個程式碼會將 --brand-hue--brand-saturation--brand-lightness 自訂屬性納入 hsl () 函式括號中,沒有任何計算:

* {
  --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 中,所有淺色顏色會集中在 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;
}
燈號全部一起的螢幕截圖
CodePen 上的沙箱

深色主題

大部分品牌一開始都沒有採用深色主題,而是主要版本 (通常是較淺色主題) 的變化版本。另一方面,使用者通常會針對不同情境 (例如夜間) 選擇深色主題。這促使我記住以下兩大 深色主題:

  1. 使用這個主題時,使用者通常處於黑暗中,因此請以深色進行測試。
  2. 色彩應過於飽和,使其不會震動,以免造成螢幕過度震動。

深色主題結束結果的預覽畫面

Brand

淺色主題使用 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;
}

此外,也要注意陰影中的飽和度。查看介面時,有沒有註意到這個顏色?您希望從開發人員工具中移除飽和度?

深色集中顯示

* {
  --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;
}
深色全部的螢幕截圖
CodePen 上的沙箱

調暗主題

這種色彩配置的重點在於亮度和飽和度。應該要有足夠的飽和度,才能顯示色調,但也應該幾乎不會傳遞「對比分數」,因為這樣還是要維持暗色與低對比。

暗色主題的結束結果預覽畫面

Brand

* {
  --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;
}
暗色全部的螢幕截圖
CodePen 上的沙箱

易懂的顏色

請注意,深色文字色彩組合中的最小亮度為 65%,深色表面中的高亮度為 25%。相當於 40% 的光線 難以置信在淺色主題中,淺色主題有 55% 的呼吸室。將文字和表面顏色之間的亮度差異維持在 40% 到 50% 左右,將有助於維持高顏色對比度,同時做為在分數不佳的情況下進行微調的細微因素。

我稱之為「讓碰觸 Y 軸傳輸」,也就是在工具顯示我的過臨前,凸顯亮度值的互動。

按住 Shift + 向下鍵可降低亮度,並在結束之前增加對比度

在此挑戰中建立的每個主題都通過對比分數。較暗的色彩配置具有最低的對比度,但仍符合最低規定。為了協助團隊中的其他人使用良好的對比顏色,建議您建立一個類別名稱,結合表面顏色和無障礙的文字顏色。

.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);
}
暗表和文字配對的螢幕截圖
昏暗介面以及與 VisBug 配對的文字螢幕截圖

輻射陰影

主題會使用名為 .rad-shadow 的公用程式類別。我非常欣賞這個「Smooth 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 中,顏色的調整和旋轉作業都比在 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-preferencemoreless 新增了色調滑桿、狀態顏色和對比模式:試用版