CSS `lch()` / `lab()` 颜色空间:感知均匀性与广色域管理

各位老铁,早上好/中午好/晚上好! 今天咱们来聊聊CSS颜色空间里的“贵族”—— lch()lab() 。这俩货听起来高大上,其实也没那么玄乎,咱争取用最接地气的方式把它俩给扒个精光。

一、前戏:为啥需要新的颜色空间?

话说当年,CSS颜色空间的世界还比较简单,RGB一家独大。RGB好用是好用,但有个致命的缺陷:它不符合人类的感知。啥意思呢?就是说,RGB值差不多的两个颜色,人眼看起来可能差异很大;而RGB值差异很大的两个颜色,人眼看起来可能差不多。这对于需要精确控制颜色的设计师和开发者来说,简直是噩梦。

比如,你想要让一个按钮的颜色逐渐变亮,用RGB控制,你会发现,亮到一半的时候,颜色可能就变得很刺眼了,或者干脆就没啥变化。这都是因为RGB在感知上是不均匀的。

所以,我们需要一种更符合人类感知的颜色空间,它能保证颜色值的变化和人眼感知的变化是线性对应的。这就是 lch()lab() 登场的理由。

二、主角登场:lab()lch() 是啥玩意?

lab()lch() 都是基于CIE Lab颜色空间建立的。CIE Lab颜色空间是由国际照明委员会(CIE)在1976年提出的,它的目标就是创建一个感知均匀的颜色空间。

  • lab() 由三个分量组成:

    • L:亮度(Lightness),取值范围是0到100,0代表黑色,100代表白色。
    • a:绿色到红色的分量,取值范围一般是-128到127,负值代表绿色,正值代表红色。
    • b:蓝色到黄色的分量,取值范围一般是-128到127,负值代表蓝色,正值代表黄色。
  • lch() 也由三个分量组成:

    • L:亮度(Lightness),和lab()里的L一样。
    • c:色度(Chroma),表示颜色的鲜艳程度,取值范围是0到理论上的无穷大,但实际使用中一般不会超过150。0代表灰色,数值越大颜色越鲜艳。
    • h:色相(Hue),表示颜色的相貌,取值范围是0到360度,0度代表红色,120度代表绿色,240度代表蓝色。

简单来说,lab()是用直角坐标系表示颜色,而lch()是用极坐标系表示颜色。lch()更符合人类对颜色的理解,因为它直接用色相、亮度和鲜艳程度来描述颜色。

三、代码实战:lch()lab() 怎么用?

在CSS中,我们可以直接使用 lch()lab() 函数来定义颜色。

/* 使用 lab() 定义一个亮红色 */
.lab-example {
  background-color: lab(60, 65, 30); /* L=60, a=65, b=30 */
  color: white;
}

/* 使用 lch() 定义一个鲜艳的蓝色 */
.lch-example {
  background-color: lch(50, 100, 250); /* L=50, C=100, H=250 */
  color: white;
}

/* 改变亮度 */
.lch-example-darker {
  background-color: lch(30, 100, 250); /* L=30, C=100, H=250 */
  color: white;
}

/* 改变色度 */
.lch-example-less-vibrant {
  background-color: lch(50, 50, 250); /* L=50, C=50, H=250 */
  color: white;
}

/* 改变色相 */
.lch-example-different-hue {
  background-color: lch(50, 100, 120); /* L=50, C=100, H=120 */
  color: white;
}

注意:

  • lch()lab() 的浏览器兼容性还不是特别好,使用前最好做一下兼容性处理(比如使用PostCSS插件)。
  • lch() 的色度(C)理论上可以无限大,但实际使用中要根据显示器的色域范围进行限制,否则可能会出现颜色溢出的问题。

四、lch() 的优势:感知均匀性

lch() 最大的优势就是它的感知均匀性。这意味着,如果你想让一个颜色逐渐变亮,只需要线性地增加 L 值即可。

/* 使用 lch() 创建一个亮度渐变的按钮 */
.button {
  background-color: lch(50, 80, 40);
  color: white;
  transition: background-color 0.3s ease;
}

.button:hover {
  background-color: lch(60, 80, 40); /* 亮度增加10 */
}

.button:active {
  background-color: lch(40, 80, 40); /* 亮度减少10 */
}

上面的代码中,我们通过改变 L 值,实现了按钮在hover和active状态下的亮度变化。这种变化是线性的,人眼看起来会非常自然。

如果用RGB来实现同样的效果,你需要进行复杂的颜色计算,而且效果还不一定好。

五、lch() 的另一大优势:广色域管理

现在的显示器越来越牛逼,色域也越来越广。传统的RGB颜色空间已经无法完全覆盖这些广色域显示器所能显示的颜色。而 lch() 可以轻松地表示超出sRGB色域范围的颜色。

/* 使用 lch() 定义一个超出 sRGB 色域范围的颜色 */
.wide-gamut-color {
  background-color: lch(70, 130, 60); /* 这个颜色在 sRGB 色域中可能无法完全显示 */
  color: white;
}

在支持广色域的显示器上,上面的代码会显示出一个非常鲜艳的绿色,而在不支持广色域的显示器上,浏览器会自动将颜色映射到sRGB色域范围内,保证颜色不会失真。

六、lch() 的应用场景:

  • 创建配色方案: lch() 可以让你更轻松地创建和谐的配色方案。你可以固定亮度 L 和色度 C,只改变色相 H,就可以得到一系列颜色相近的颜色。

    /* 创建一个基于 lch() 的配色方案 */
    :root {
      --primary-color: lch(60, 80, 200); /* 主色 */
      --secondary-color: lch(60, 80, 230); /* 次要色,色相稍微偏移 */
      --accent-color: lch(60, 80, 320); /* 强调色,色相偏移较大 */
    }
    
    .primary {
      background-color: var(--primary-color);
      color: white;
    }
    
    .secondary {
      background-color: var(--secondary-color);
      color: white;
    }
    
    .accent {
      background-color: var(--accent-color);
      color: white;
    }
  • 创建颜色渐变: lch() 可以让你创建更平滑、更自然的颜色渐变。

    /* 使用 lch() 创建一个颜色渐变 */
    .gradient {
      background: linear-gradient(to right, lch(50, 80, 20), lch(50, 80, 140));
    }
  • 动态调整颜色: lch() 可以让你在运行时动态调整颜色,而不会出现颜色失真的问题。这对于创建交互式界面非常有用。

    // JavaScript 代码
    const button = document.querySelector('.dynamic-color-button');
    
    button.addEventListener('click', () => {
      // 随机改变色相
      const hue = Math.random() * 360;
      button.style.backgroundColor = `lch(50, 80, ${hue})`;
    });
  • 数据可视化: 在数据可视化中,使用 lch() 可以更准确地表达数据的差异,避免颜色引起的视觉偏差。

七、一些需要注意的点:

  • 颜色空间转换: 如果你需要将RGB颜色转换为 lch()lab() 颜色,可以使用一些在线工具或JavaScript库。比如 chromajs

    // 使用 chromajs 将 RGB 颜色转换为 lch 颜色
    const rgbColor = [255, 0, 0]; // 红色
    const lchColor = chroma(rgbColor).lch();
    console.log(lchColor); // 输出 lch 颜色数组
  • 颜色校准: 为了保证颜色显示的准确性,最好对显示器进行颜色校准。

  • 浏览器兼容性: 在使用 lch()lab() 之前,一定要做好浏览器兼容性处理。

八、lch()lab() 的参数范围和取值

为了更清晰地了解 lch()lab(),我们使用表格总结一下它们的参数范围和取值:

参数 颜色空间 描述 范围 (典型值) 单位
L lab(), lch() 亮度 (Lightness) 0 – 100
a lab() 绿色到红色分量 -128 – 127
b lab() 蓝色到黄色分量 -128 – 127
c lch() 色度 (Chroma) 0 – ∞ (常用 0 – 150)
h lch() 色相 (Hue) 0 – 360 deg
/ <alpha-value> lab(), lch() 透明度 0 – 1

九、兼容性问题的解决:PostCSS 大法好!

lch()lab() 虽然香,但是浏览器兼容性是个老大难问题。这时候,就得请出我们的老朋友——PostCSS!

PostCSS 是一个强大的 CSS 处理工具,可以通过插件来扩展其功能。我们可以使用 postcss-preset-env 插件来自动将 lch()lab() 转换为浏览器支持的颜色格式。

  1. 安装 PostCSS 和 postcss-preset-env

    npm install postcss postcss-cli postcss-preset-env --save-dev
  2. 创建 PostCSS 配置文件(postcss.config.js):

    module.exports = {
      plugins: [
        require('postcss-preset-env')({
          stage: 3, // 使用 stage 3 的特性
          features: {
            'color-function': { // 启用 color-function 特性
              preset: 'default'
            }
          },
          browsers: 'last 2 versions' // 兼容最近两个版本的浏览器
        })
      ]
    };
  3. 在 package.json 中添加 PostCSS 命令:

    {
      "scripts": {
        "postcss": "postcss src/css/style.css -o dist/css/style.css"
      }
    }
  4. 运行 PostCSS 命令:

    npm run postcss

这样,PostCSS 就会自动将你的 CSS 文件中的 lch()lab() 转换为浏览器支持的颜色格式,例如 rgba()

十、总结:lch()lab(),未来可期!

lch()lab() 颜色空间是CSS颜色发展的重要方向。它们能够更好地满足设计师和开发者对颜色的精确控制和感知一致性的需求。虽然目前的浏览器兼容性还不是特别好,但随着浏览器的不断更新,lch()lab() 的应用前景将越来越广阔。

所以,各位老铁,赶紧学起来,用起来,让你的网页颜色更鲜艳,更和谐,更符合人类的审美!

今天的讲座就到这里,感谢大家的收听!希望对大家有所帮助! 下课!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注