博客 / 詳情

返回

品牌色功能迭代方案

最近產品經理希望在 B 端後台系統中增加品牌色功能,突顯客户的企業特色。從技術上説,整個流程是非常簡單的:

  1. 在配置中心為某個客户配置品牌色(十六進制顏色值)。
  2. 後台系統初始化時,通過後端接口讀取配置的品牌色。
  3. 把品牌色寫入為根元素的 CSS 變量

核心流程代碼如下:

const response = await fetch('/api/get-brand-info');
const data = await response.json();
document.documentElement.style.setProperty(
  '--brand-primary-color',
  data.primaryColor
);

顏色替換

接下來要把項目中樣式代碼的顏色值改為 CSS 變量。顏色值的使用,一般有兩種情況:

  • 使用了 SCSS 等 CSS 擴展語言中的變量,所有顏色值都從變量取值;
  • 直接用顏色值。

實際情況更有可能是這兩種的混合——雖然使用了 SCSS 變量,但由於部分開發人員沒有完全遵循規範,所以項目中既有顏色變量,也有顏色值。

$primary-color: #3F76FC;

.logo {
  background: #3F76FC;
}
.selected {
  color: $primary-color;
  border: 1px solid $primary-color;
  background: rgba($primary-color, 0.1);
}

不過,不管是哪種情況,似乎都是把顏色值替換成 CSS 變量就可以了。以上述代碼為例,即把#3F76FC 替換為 var(--brand-primary-color, #3F76FC):

$primary-color: var(--brand-primary-color, #3F76FC);

.logo {
  background: var(--brand-primary-color, #3F76FC);
}
.selected {
  color: $primary-color;
  border: 1px solid $primary-color;
  background: rgba($primary-color, 0.1);
}

替換後,馬上發現問題——.selected 元素的背景色沒了。通過瀏覽器開發工具可以發現,背景屬性的值變成了:

background: rgba(var(--brand-primary-color, #3F76FC), 0.1);

屬於無效寫法。造成這種情況,是因為「background: rgba($primary-color, 0.1)」中的「$primary-color」被編譯成該變量的值了。

在 SCSS 中,可以用「rgba(#3F76FC, 0.1)」這種寫法。編譯過程中,編譯器會把十六進制顏色值轉成 RGB 顏色值,也就是編譯成「rgba(63, 118, 252, 0.1)」。然而,把顏色值替換成 CSS 變量後,由於編譯器也不知道顏色值是什麼,所以無法進行轉換。因此,這裏必須用 RGB 顏色值

對核心流程代碼稍作修改,設置兩個 CSS 變量,分別是 RGB 顏色值和十六進制顏色值:

import { hexToRGB } from '@polyv/utils/es/color';

const response = await fetch('/api/get-theme');
const data = await response.json();
document.documentElement.style.setProperty(
  '--brand-primary-color-hex',
  data.primaryColor
);
document.documentElement.style.setProperty(
  '--brand-primary-color-rgb',
  hexToRGB(data.primaryColor).join(',')
);

接下來設置兩個 SCSS 變量,分別是品牌色的十六進制表示和 RGB 表示:

$--primary-color-hex: var(--brand-primary-color-hex, #3F76FC);
$--primary-color-rgb: var(--brand-primary-color-rgb, 63, 118, 252);

做兩次替換操作:

  1. rgba($--primary-color 以及 rgba(#3F76FC 替換為 rgba($--primary-color-rgb
  2. 把剩餘的 $--primary-color 以及 #3F76FC 替換為 $--primary-color-hex

最終能正常運行的代碼為:

$--primary-color-hex: var(--brand-primary-color-hex, #3F76FC);
$--primary-color-rgb: var(--brand-primary-color-rgb, 63, 118, 252);

.logo {
  background: $--primary-color-hex;
}
.selected {
  color: $--primary-color-hex;
  border: 1px solid $--primary-color-hex;
  background: rgba($--primary-color-rgb, 0.1);
}

顏色計算

設計師希望後台系統左側導航欄的底色是通過 25% 不透明度的品牌色疊加黑色得出。

導航欄

雖説通過兩個 HTML 元素疊加,就能做到這個效果,但是 HTML 結構和樣式代碼都會稍顯複雜。通過 JavaScript 去計算出這個顏色值就方便多了:

export function mixWithBlack(color, opacity) {
  const r = parseInt(hex.slice(0, 2), 16) * opacity;
  const g = parseInt(hex.slice(2, 4), 16) * opacity;
  const b = parseInt(hex.slice(4, 6), 16) * opacity;
  const toHex = (c) => c.toString(16).padStart(2, '0');
  return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}

document.documentElement.style.setProperty(
  '--brand-nav-bg-color',
  mixWithBlack(data.primaryColor)
);

如果還有更復雜的顏色計算,也可以使用專業的第三方庫,如 tinycolor。

最終效果

整頁效果

本文也發表在作者個人博客 https://mrluo.life/article/detail/156/technical-implementatio...

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.