news 2026/2/17 2:11:07

现代 CSS 颜色使用指南进阶篇

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
现代 CSS 颜色使用指南进阶篇

在上篇文章,我们学会了现代 CSS 颜色的基础用法。

本篇我们进入更高级的领域:如何像设计师一样操纵颜色

CSS 现在能做的事情,甚至比设计软件还要强大!

1. 操纵颜色

1.1. 基础回顾

先复习一下上篇文章的内容:

:root{--primary:#ff0000;}.primary-bg-50-opacity{/* h s l 不是字母,是变量! */background:hsl(fromvar(--primary)h s l / 0.5);}

注意:h s l这三个字母其实是变量,分别存储了色相(hue)、饱和度(saturation)、亮度(lightness)的值。

我们可以替换这些变量,比如给绿色(#00ff00)加点蓝:

/* 基础绿色没有蓝色成分 */.green-with-a-touch-of-blue{/* 在蓝色通道加 25 */color:rgb(from #00ff00 r gcalc(b + 25));}

这就像调色板,在基础的绿色中,添加点“蓝色颜料”。

1.2. 实用技巧

掌握了基础用法,我们就可以讲些实际开发中会用到的场景了。

  1. 创建互补色(色轮对面的颜色):
:root{--color-primary:#2563eb;/* 蓝色 *//* 色相加 180 度,跳到对面 */--color-secondary:hsl(fromvar(--color-primary)calc(h + 180)s l);}
  1. 创建三色组合:
:root{--color-primary:#2563eb;/* 色轮上均匀分布 120 度 */--color-secondary:hsl(fromvar(--color-primary)calc(h + 120)s l);--color-tertiary:hsl(fromvar(--color-primary)calc(h - 120)s l);}

就像时钟:12 点是主色,4 点和 8 点是配色,完美对称!

使用效果如下:

  1. 相对调整
:root{--color-primary-base:#2563eb;/* 比基础色亮 25% */--color-primary-lighter:hsl(fromvar(--color-primary-base)h scalc(l + 25));/* 比基础色暗 25% */--color-primary-darker:hsl(fromvar(--color-primary-base)h scalc(l - 25));}

使用这种方法,不管基础色是多亮,都会相对地变亮或变暗。

这就像调空调,“比现在低 5 度”比“设定到 20 度”更灵活。

使用效果如下:

2. 暗黑模式的层次感

现在我们能相对调整颜色了,可是究竟有什么用呢?

让我给你举个具体的使用场景。

在浅色主题中,我们可以根据阴影来区分层次:

但在深色背景下,阴影的效果并不明显。

因此在深色主题中,我们希望每个层次的颜色略微变浅。

借助上篇讲过的light-dark()和相对颜色调整,我们便可以实现:

:root{--surface-base-light:hsl(240 67% 97%);--surface-base-dark:hsl(252 21% 9%);}/* 第一层:基础层 */.surface-1{background:light-dark(var(--surface-base-light),var(--surface-base-dark));}/* 第二层:稍微亮一点 */.surface-2{background:light-dark(var(--surface-base-light),hsl(fromvar(--surface-base-dark)h scalc(l + 4)));}/* 第三层:再亮一点 */.surface-3{background:light-dark(var(--surface-base-light),hsl(fromvar(--surface-base-dark)h scalc(l + 8)));}

想象一下深海:越接近水面,光线越充足。暗色模式的层次就是这个原理。

使用效果如下:

3. 完整配色方案

设计师创建配色方案时,不只是简单地调整亮度,还会同时微调色相和饱和度,比如

  • 变亮时:饱和度增加,色相向冷色调偏移
  • 变暗时:饱和度降低

这便可以通过 CSS 来实现:

:root{--primary-base:hsl(221 83% 50%);/* 400: 亮度60%,色相-3度,饱和度+5% */--primary-400:hsl(fromvar(--primary-base)calc(h - 3)calc(s + 5)60%);/* 300: 亮度70%,色相-6度,饱和度+10% */--primary-300:hsl(fromvar(--primary-base)calc(h - 6)calc(s + 10)70%);/* 以此类推... */}

为什么要这么麻烦呢?

因为只调亮度会让浅色看起来“失去活力”。

就像拍照:自动模式能拍,但手动调整曝光、对比度、色温会更漂亮。

为了让你更直观地看到变化:

第一排是都调整的版本,第二排是未调整色相和饱和度的版本。

最明显的区别在于 100、200 和 300 这几个色块,当仅调整亮度值时,颜色看起来失去了一些鲜艳度。

4. OKLCH 更科学的配色方式

4.1. 问题:HSL

HSL 虽然很棒,但在使用时,你会发现一些问题,让我们看个例子:

.green-bg{/* 饱和度 100%,亮度 50% */background:hsl(100 100% 50%);color:white;}.blue-bg{/* 同样饱和度 100%,亮度 50% */background:hsl(220 100% 50%);color:white;}

你会发现,色和蓝色的饱和度、亮度虽然完全一样,但视觉效果完全不同:

明显蓝色背景上的文字清晰易读,对比度超过 5,而绿色背景上的文字却很难看清,对比度仅略高于 1。

之所以会这样,是因为 HSL 的“亮度”不符合人眼感知。

人眼对绿色比蓝色更敏感,所以同样的“50%亮度”,绿色看起来更亮。

4.2. 解决:OKLCH

而这就是 oklch() 的优势。

OKLCH 是基于感知亮度设计的:

.consistent-green{background:oklch(0.54 0.23 261);}.consistent-blue{background:oklch(0.54 0.23 146);}

使用效果如下:

现在不管什么颜色,亮度值相同,人眼看起来的亮度就相同!

4.3. 讲解:OKLCH 的三个参数

在 LCH 颜色模型中:

第一个值是亮度(Lightness),取值范围为 0 到 1。它的计算方式与 HSL 略有不同,因为它基于感知亮度,但概念相同,即 0 是黑色,1 是白色。

第二个值是色度(Chroma),类似于饱和度,0 是灰色,越大越鲜艳,但最大值不固定,取决于亮度和色相(这是 OKLCH 最麻烦的地方)

第三个值是色相(Hue),和 HSL 一样是色轮,0 到 360 度,区别是 0 度是洋红色(HSL 里 0 度是红色)

OKLCH 的尴尬之处就在于色度(Chroma)的最大值会变:

/* 某些色相+亮度组合,0.4 已经是极限 */.max-chroma-1{background:oklch(0.6 0.4 120);}/* 但另一些组合,0.4 可能太高或太低 */.max-chroma-2{background:oklch(0.8 0.4 200);/* 可能超出范围 */}

就像不同口味的饮料,有的最浓是“3 勺糖”,有的最浓是“5 勺糖”,没有统一标准。

4.4. 实用技巧:结合相对颜色

虽然直接写 OKLCH 值很麻烦,但我们可以用 HSL 定义基础色,然后用 OKLCH 保持一致性:

.toast{--base-color:hsl(225,87%,56%);/* 用熟悉的 HSL 定义 */}[data-toast="info"]{/* 只改变色相,保持亮度和色度 */--toast-color:oklch(fromvar(--base-color)l c 275);}[data-toast="warning"]{--toast-color:oklch(fromvar(--base-color)l c 80);}[data-toast="error"]{--toast-color:oklch(fromvar(--base-color)l c 35);}

使用效果如下:

这样做的好处在于:不同颜色的提示框,边框对比度、整体饱和度感觉都很一致。

5. 混合颜色

有的时候,我们可能需要混合两种颜色:

.purple{/* 红色和蓝色各占 50% */color:color-mix(in srgb,red,blue);}

就像调颜料:红色颜料加蓝色颜料,得到紫色。

目前必须定义一个颜色空间,所以必须写in srgbin oklab等,未来会默认用oklab

不同颜色空间混出来的结果不一样:

一般推荐:

  1. 先试oklab
  2. 再试oklch
  3. 不满意就换其他的

5.1. 控制混合比例

默认情况下,使用该功能时color-mix(),每种颜色将使用 50% 的强度。

当然,我们也可以控制特定颜色的具体强度。

/* 90% 红色 + 10% 蓝色 */.red-with-a-touch-of-blue{background:color-mix(in oklab,red 90%,blue);}/* 或者反过来写 */.or-like-this{background:color-mix(in oklab,red,blue 10%);}

5.2. 创建半透明色

有两种方法可以获得透明的值:

方法一:让总量小于 100%

/* 60% + 20% = 80%,所以透明度是 80% */.semi-opaque{background:color-mix(in oklab,red 60%,blue 20%);}

方法二:混入 transparent

/* 30% 的不透明红色 */.thirty-percent-opacity-red{background:color-mix(in oklch,red 30%,transparent);}

不过如果只是想降低透明度,还是用相对颜色更直接:

.better-way{background:rgb(from red r g b / 0.3);}

5.3. 小技巧:分段渐变

/* 不用手动算中间的每个颜色,color-mix 帮你搞定 */.banded-gradient{background:linear-gradient(to right,red,color-mix(in oklch,red 75%,blue),color-mix(in oklch,red 50%,blue),color-mix(in oklch,red 25%,blue),blue);}

使用效果如下:

6. 未来更简单

重复写这些代码很烦?

CSS 自定义函数快来了:

/* 定义函数 */@function--lower-opacity(--color,--opacity){result:oklch(fromvar(--color)l c h /var(--opacity));}/* 使用函数 */.lower-opacity-primary{background:--lower-opacity(var(--primary),0.5);}

或者定义整套色阶函数:

@function--shade-100(--color)returns <color>{result:hsl(fromvar(--color)calc(h - 12)calc(s + 15)95%);}@function--shade-200(--color)returns <color>{result:hsl(fromvar(--color)calc(h - 10)calc(s + 12)85%);}/* 以此类推... */.call-to-action{background:--shade-200(var(--accent));}.hero{background:--shade-800(var(--primary));color:--shade-100(var(--primary));}

一次定义,到处使用,完美!

7. 总结

最后总结下本篇文章的重点:

  1. 用 calc() 操纵颜色- 数学生成配色方案
  2. OKLCH- 基于人眼感知的颜色系统,不同色相亮度一致
  3. color-mix()- 像调颜料一样混合颜色

在实际使用时:

  • 简单需求:相对颜色 + HSL
  • 需要视觉一致性:OKLCH
  • 需要混合颜色:color-mix()
  • 暗黑模式层次:light-dark() + 相对颜色

本篇整理自《A pragmatic guide to modern CSS colours - part two》,希望能帮助到你。

我是冴羽,10 年笔耕不辍,专注前端领域,更新了 10+ 系列、300+ 篇原创技术文章,翻译过 Svelte、Solid.js、TypeScript 文档,著有小册《Next.js 开发指南》、《Svelte 开发指南》、《Astro 实战指南》。

欢迎围观我的“网页版朋友圈”,关注我的公众号:冴羽(或搜索 yayujs),每天分享前端知识、AI 干货。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/15 4:31:12

20 周年之际!jQuery 4.0 正式发布!轻装上阵

2006 年 1 月 14 日&#xff0c;John Resig 发布了名为 jQuery 的 JavaScript 库。 至今已经整整过去了 20 年&#xff01; 你还记得第一次在项目中使用 jQuery 的场景吗&#xff1f; 在那个浏览器兼容性让人头疼&#xff0c;DOM 操作繁琐复杂的时代&#xff0c;jQuery 凭借…

作者头像 李华
网站建设 2026/2/16 14:17:23

杨洋官宣周大福全球品牌代言人 以从容姿态定义璀璨新篇

1月16日&#xff0c;周大福正式官宣演员杨洋成为全球品牌代言人及首席传福官。独立笃行&#xff0c;清俊从容&#xff0c;杨洋以其独特的个人魅力&#xff0c;将金饰的质感融入自身风格&#xff0c;于光影间展露矜贵本色&#xff0c;演绎出别具一格的现代绅士风范。 在视频中&a…

作者头像 李华
网站建设 2026/2/6 2:30:50

炒股别太努力:量化交易正在“收割”最认真的投资者?

当勤奋成为亏损的陷阱在多数领域&#xff0c;深入研究和勤奋分析是通往成功的不二法门。我们从小就被教导&#xff0c;付出越多&#xff0c;收获越大。然而&#xff0c;在当前的A股市场&#xff0c;这个看似颠扑不破的逻辑可能正在失效&#xff0c;甚至会适得其反。当下的市场主…

作者头像 李华
网站建设 2026/2/15 8:36:27

Uniapp苹果内购支付全流程指南:从集成到配置的完整复盘

引言在移动应用开发中&#xff0c;虚拟商品支付是核心功能之一&#xff0c;而针对iOS平台&#xff0c;苹果App Store强制要求虚拟商品必须通过其官方内购渠道完成交易&#xff0c;这使得Uniapp项目集成苹果内购成为iOS端开发的必备技能。本文将全面复盘Uniapp苹果内购支付的完整…

作者头像 李华
网站建设 2026/2/9 0:06:30

AI Agent yyds!5分钟带你入门智能体开发,小白也能轻松上手

第一章&#xff1a;初识智能体 欢迎来到智能体的世界&#xff01;在人工智能浪潮席卷全球的今天&#xff0c;**智能体&#xff08;Agent&#xff09;**已成为驱动技术变革与应用创新的核心概念之一。无论你的志向是成为AI领域的研究者、工程师&#xff0c;还是希望深刻理解技术…

作者头像 李华