> 作者：五灵

本周工作中遇到类似颜色主题的问题，在查资料的时候，看到这个视频，觉得讲得很清楚，而且趣味性丰富，所以想拿出来讲讲这个很有意思的主题。

视频链接： [CSSconf EU 2018 | Dag-Inge Aas & Ida Aalen: Generating Colors with JS and CSS Custom Properties](https://www.youtube.com/watch?v=zi6L0ZqrKfA)

## 1. 精读

### CSS 变量

CSS 变量及 CSS Variables(Custom Properties)，目前几乎都已经被主流浏览器所支持，但是估计还有一部分读者不熟悉这个功能，简单列举一下使用方法：

```css
:root {
  --bg-color: brown; // 定义颜色变量
}
.btn {
  // 直接使用颜色预定义的颜色变量
  background-color: var(--bg-color);
}
```

### Web 内容无障碍指南的对比度

Web 内容无障碍指南的对比度指的是 W3C 组织发布的 [《Web Content Accessibility Guidelines (WCAG)》](https://www.w3.org/TR/WCAG/#glossary)，这个指南中涵盖了让 Web 内容更易于访问的各种建议，其中针对网页的颜色对比度发布了规范。

在 Chrome 中对于颜色编辑的时候，打开颜色选择器也会看到当前颜色的对比度值（Contrast ratio）。

![](https://img.alicdn.com/tfs/TB1VQUveRv0gK0jSZKbXXbK2FXa-260-388.png)

网页颜色的对比度值在 1：1 到 21：1 之间，文本和图像文本的的对比度最小值为 4.5:1，也就是说低于这个值得对比度都不符合标准。 我们看一下列举的几种颜色对比度，对比度越高，也越有利于阅读。对比度越低，对于一些存在视力障碍或色觉缺陷的用户，可能就无法阅读。

![](https://img.alicdn.com/tfs/TB1G1MveUz1gK0jSZLeXXb9kVXa-1000-410.png)

### 演讲中的颜色解决方案

演讲在最开始首先讲了挪威的一个法律，不符合 Web 内容无障碍指南的站点在挪威是非法的，所以挪威的 Web 开发者非常注重站点的内容无障碍。

首先讲了使用 css 变量的方式，支持各种颜色主题的切换。 利用 js 去设置颜色变量，支持主题的颜色切换。

但是紧接着就提出了问题，如果用户可以随意切换颜色主题背景色，那一些按钮的文字可读性如何去保障呢？如果用户选择了与按钮颜色想接近的背景色，我们又该怎么处理了，紧接着这个演讲给出了根据明度决定按钮文字颜色是黑色还是白色的方案。

- 根据明度决定是黑色还是白色

具体代码如下，大致原理是把彩色转为灰度的颜色，有一个著名的心理学公式：`Gray = R*0.299 + G*0.587 + B*0.114`,然后在根据颜色灰度决定使用黑色的主题还是白色的主题。

```javascript
if (red*0.299 + green*0.587 + blue*0.114) > 186 use #000000 else use #ffffff
```

![](https://img.alicdn.com/tfs/TB1zfcveUz1gK0jSZLeXXb9kVXa-1535-584.png)

可读性的问题解决了，但是紧接着又遇到了一个问题，如果用户选取的颜色很浅呢，与背景颜色的对比度小于 4.5，该怎么处理呢。

![](https://img.alicdn.com/tfs/TB14RsveQP2gK0jSZPxXXacQpXa-1254-402.png)

- 寻找对比度更强的颜色，增强可读性

演讲中给出的解决方法是不断的加深当前用户选择的颜色，循环获取到对比度最高的同色系颜色。代码如下：

![](https://img.alicdn.com/tfs/TB19J7veUH1gK0jSZSyXXXtlpXa-1457-663.png)

获取了一个更深的颜色后，通过给按钮加一个外边框的方式，优化整体的可读性。

![](https://img.alicdn.com/tfs/TB1aRQzeUY1gK0jSZFCXXcwqXXa-1802-571.png)

文章最后还介绍了，通过给定一个主题色，获取第二第三主题色的方式，通过将颜色放到 HSL 的颜色轮上，转动 hue 的值 60 度，得到一个新的第二主题色。不过演讲者也没有说清楚为什么要这么做，只是说了这么做是出于经验，觉得这样能够得到一个恰当的主题色盘。

### 衍生的纯 css 解决方案

演讲中提供颜色变更的解决方案基本都是基于 JS 计算的，后来有人在 [css-tricks](https://css-tricks.com/switch-font-color-for-different-backgrounds-with-css/) 抛出一篇文章说，这个功能基于 css 就可以完全实现，其实关于颜色的原理都是一致的，只是觉得这个实现更加 magic，但是功能都能够完全满足。比如这篇文章中，关于根据明度决定按钮文字是黑色还是白色的代码如下：

```css
:root {
  --light: 80;
  /* 文字颜色变化的临界值 */
  --threshold: 60;
}
.btn {
  /* 会被解析成黑色或者白色 */
  --switch: calc((var(--light) - var(--threshold)) * -100%);
  color: hsl(0, 0%, var(--switch));
}
```

### 可视化图表对于颜色的应用

在可视化图表当中，对于颜色的应用要比 Web 要谨慎的多。我们在做 Web 开发的时候，也不妨来看一下可视化图表当中对于颜色应用的一些规范。在可视化图表中，选择的颜色不可以过于随意，每次颜色的变更都是图表信息的改变，都为图表增加了新的数据，图表的每一种颜色也是要表达的信息。列举一些图表中的颜色使用规范，比如：

1. 不建议使用多种颜色表达同种数据
2. 在多条行图表中，不要使用不同的颜色或颜色轮中对立面的颜色。颜色对比过强会使读者无法专心于数据。
3. 一般而言，应避免颜色的主体性表现，避免使用具有特殊意义的颜色。比如使用红色和绿色表示销售额的变化。

当然对于可视化图表来说，并不是遵循了一些色彩使用的准则，就可以得到一个优雅呈现的可视化图表。注重图表呈现的最重要的视觉元素，在视觉信息角度减少用户，减少用户视觉疲劳也很重要。

## 3. 相关链接

CSS 前景背景自动配色技术简介: [https://www.zhangxinxu.com/wordpress/2018/11/css-background-color-font-auto-match/](https://www.zhangxinxu.com/wordpress/2018/11/css-background-color-font-auto-match/)<br />
纯 css 解决方案：[https://css-tricks.com/switch-font-color-for-different-backgrounds-with-css/](https://css-tricks.com/switch-font-color-for-different-backgrounds-with-css/)<br />
获取颜色的 Demo： [https://confrere.com/a11y/test/](https://confrere.com/a11y/test/)<br />
颜色色盘推荐的文章：[https://blog.graphiq.com/finding-the-right-color-palettes-for-data-visualizations-fcd4e707a283](https://blog.graphiq.com/finding-the-right-color-palettes-for-data-visualizations-fcd4e707a283)

> 讨论地址是：[精读《使用 css 变量生成颜色主题》 · Issue #203 · dt-fe/weekly](https://github.com/dt-fe/weekly/issues/203)

**如果你想参与讨论，请 [点击这里](https://github.com/dt-fe/weekly)，每周都有新的主题，周末或周一发布。前端精读 - 帮你筛选靠谱的内容。**

> 关注 **前端精读微信公众号**

<img width=200 src="https://img.alicdn.com/tfs/TB165W0MCzqK1RjSZFLXXcn2XXa-258-258.jpg">

> 版权声明：自由转载-非商用-非衍生-保持署名（[创意共享 3.0 许可证](https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh)）
