contrast-color():在 CSS 中让浏览器给出对比色
你是否曾希望自己能编写简单的 CSS 来声明一种颜色,然后让浏览器计算出这种颜色应该搭配黑色还是白色?现在有了 contrast-color()
,你就可以做到了。下面是它的工作原理。
想象一下,我们正在创建一个网站或网络应用,设计要求使用不同背景颜色的按钮。我们可以创建一个名为 --button-color
的变量来处理背景颜色。然后在不同情况下,从我们的设计系统中为该变量分配不同的值。
有时,按钮背景会是深色,而按钮文字应该是白色,以形成对比。有时,背景颜色较浅,文字应为黑色。就像这样
两个并排的按钮。第一个按钮的背景是深紫色,文字为白色;第二个按钮的背景是粉红色,文字为黑色。
当然,我们也可以使用第二个变量来定义文字颜色,同时仔细定义 --button-color
和 --button-text-color
的值,这样就能确保文字颜色的选择是正确的。但是,在一个大型项目中,如果有一个庞大的团队,仔细管理这些细节就会变得非常困难。突然间,一个深色的按钮变成了难以辨认的黑色文字,用户就不知道该怎么办了。
如果我们能告诉 CSS 让文字变成黑色/白色,然后让浏览器选择使用哪种颜色–哪种颜色与特定颜色的对比度更高–那就简单多了。这样,我们就可以管理多种背景颜色,而不用担心文字颜色了。
这正是我们可以使用 contrast-color()
函数做到的。
contrast-color()
我们可以在 CSS 中这样写
color: contrast-color(purple);
这样,浏览器就会将color
设置为黑色或白色,无论哪种颜色都能与purple
形成更好的对比。
让我们来为按钮设计样式。我们将把按钮背景颜色设置为变量。然后将文字颜色定义为与该变量匹配的黑/白对比色。
button {
background-color: var(--button-color);
color: contrast-color(var(--button-color));
}
现在我们只需定义一种颜色,其他颜色就会随之出现!当我们改变按钮颜色时,浏览器会重新考虑文字应该是黑色还是白色,并重新选择对比度更高的选项。
为了好玩,我们还可以使用 “相对颜色语法 ”定义一种悬停颜色,现在一个变量就能决定四种颜色–默认按钮颜色和与之搭配的文字,再加上悬停颜色和与之搭配的文字。
:root {
--button-color: purple;
--hover-color: oklch(from var(--button-color) calc(l + .2) c h);
}
button {
background-color: var(--button-color);
color: contrast-color(var(--button-color));
text-box: cap alphabetic; /* vertically centers the text */
}
button:hover {
background-color: var(--hover-color);
color: contrast-color(var(--hover-color));
}
下面是效果演示。请在 Safari 技术预览版中试用,您可以动态更改按钮颜色。
可访问性考虑因素和对比度算法
现在,我们可能很容易相信,contrast-color()
会神奇地自行解决所有对比度无障碍问题,您的团队再也不用考虑颜色对比度的问题了。不,事实并非如此。完全不是这样。
使用 contrast-color()
函数并不能保证生成的一对颜色是无障碍的。我们完全有可能选择一种与黑色或白色对比度不够的颜色(本例中为背景色)。这仍然需要设计人员、开发人员、测试人员等相关人员来确保有足够的对比度。
事实上,如果你现在(本文发布于 2025 年 5 月)在 Safari 技术预览版中试用我们的演示,你会发现许多与中间色调背景颜色的搭配都无法产生足够的对比度。经常会出现选择错误的情况。例如,#317CFF 蓝色的对比色为黑色。
白色显然是更好的对比色。
这里发生了什么?为什么会选择对比度较低的呢?
Safari 技术预览版目前使用的是 WCAG 2(《网页内容可访问性指南》第 2 版)中正式定义的对比度算法。如果我们用 WebAIM 上备受推崇的色彩对比度检查器来检查这种蓝色,它会明确建议使用黑色而不是白色作为文本颜色。WCAG 2 是目前权威的网络无障碍标准,在很多地方都有法律要求。
根据 WCAG 2 算法计算,黑底#317CFF 的对比度为 5.45:1,而白底#317CFF 的对比度为 3.84:1。contrast-color()
函数只是选择数字较大的选项,而 5.45 比 3.84 大。

当机器运行 WCAG 2 算法时,黑色文本在数学上具有更高的对比度。但当人类观察这些组合时,黑色文字在感知上的对比度较低。如果你觉得奇怪,那么,你并不是唯一的一个。长期以来,WCAG 2 的色彩对比度算法一直饱受批评。事实上,将 WCAG 升级到 3 级的主要动力之一就是希望改进对比度算法。
无障碍感知对比度算法 (APCA) 是 WCAG 3 中的一个可能候选算法。您现在就可以通过 apcacontrast.com 上的 APCA 对比度计算器来尝试这种算法。让我们来看看它是如何看待黑色与白色文字在这一特定蓝色背景上的对比的。

该对比度算法认为蓝底黑字的对比度为 Lc 38.7,而蓝底白字的对比度为 Lc -70.9。要知道哪个对比度更高,请先忽略负号,然后比较 38.7 和 70.9。数字越大,对比度越高。APCA 测试结果表明,白色文本明显优于黑色文本。感觉完全正确。
(在 APCA 评分系统中,负数仅仅表示文字比背景浅。浅色模式 = 正数,深色模式 = 负数)。
为什么 APCA 能给出比 WCAG 2 更好的结果?因为它的算法是通过感知来计算对比度的,而不是通过简单的数学计算。这就考虑到了这样一个事实,即人类对色调和明度的对比度感知并不是线性的。如果您了解过 LCH 与 HSL 色彩模型,就可能听说过色彩数学的新方法如何更好地理解我们对明度的感知,并知道哪些颜色似乎具有相同的亮度或色调。APCA 分数中的 “Lc ”代表 “亮度对比”,如 “Lc 75”。
幸运的是,contrast-color
功能背后的算法可以互换。2021 年 3 月,Safari 技术预览版 122 首次支持这一功能。 (而且,当时它还被命名为 “color-contrast
“)当时,选择更好的算法还为时过早。
CSS 标准仍要求浏览器使用较旧的算法,但对未来作了说明: “目前只支持 WCAG 2.1,但众所周知,这种算法存在问题,尤其是在深色背景下。本模块今后的修订可能会引入更多对比度算法”。关于哪种算法最适合 WCAG 3 的争论仍在继续,包括对正在考虑的算法许可的讨论。
与此同时,您的团队在选择调色板时仍应非常谨慎,并牢记无障碍性。如果您要为对比色选择明显的浅色或深色,那么即使使用 WCAG 2 算法,contrast-color()
也能很好地发挥作用。在评估中间色调的对比度时,两种算法的结果开始出现差异。
此外,仅凭contrast-color()
函数永远无法保证无障碍,即使更新了更好的算法也是如此。“这种颜色对比度更高 “与 ”这种颜色对比度足够 “是两码事。有很多颜色与黑色或白色都没有足够的对比度,尤其是在文字较小或字体较细的情况下。
在现实世界中提供足够的对比度
在考虑色彩对比度的同时,我们还应该记住另一个确保为所有人提供良好对比度的工具–prefers-contrast
媒体查询。通过它,我们可以为需要更多对比度的用户提供其他样式。
@media (prefers-contrast: more) {
/* styling with more contrast */
}
让我们思考一下如何在实际情况中使用这些工具。想象一下,我们正在为一家苗圃创建一个网站,其品牌主色调是一种特殊的明亮中绿色。我们的设计团队非常希望使用 #2DAD4E 作为主按钮背景。
为了简单起见,我们还可以假设在未来,APCA 算法已经取代了 CSS 中的 WCAG 2 算法。这一变化意味着contrast-color()
将返回白色文字颜色与中绿色的对比,而不是黑色。
但是,在查看这种颜色组合时,我们会发现对于某些用户来说,对比度可能不够,尤其是在文字较小的情况下。这就是良好设计的重要性所在。
当使用这种绿色作为白色文字的背景时,APCA 得分为 Lc -60.4。
您可能还记得,WCAG 2 是用一个比率(如 “2.9:1”)来评估对比度的。然而,APCA 分数是一个单一的数字,范围从 Lc -108 到 106。Lc -60.4 是否具有足够的对比度取决于文字有多大,而在 APCA 中,字体的粗细也是一个新问题。
在 APCA 可读性标准中,有关于铜级、银级和金级的良好目标的信息。这些建议确实有助于指导设计者选择文字的大小和重量,以确保足够的对比度,同时允许一系列漂亮的颜色组合。事实上,WCAG 3 本身的设计目的就是提供灵活的指导,帮助您了解如何为所有用户提供支持,而不是像 WCAG 2 那样进行二元判断。良好的无障碍性并不是简单地满足一个神奇的指标,在列表上打勾。而是要了解什么对真实的人有用,并为他们设计。而人们的需求是复杂的,不是二元对立的。
你会注意到,这个特殊的 APCA 对比度计算器不仅提供了一个分数,还评估了显示字体大小和字体重量组合的动态示例的成功率。在我们的例子中,对于 “使用情况”,它显示 “流畅的文字还可以”(对于上面的蓝底黑字例子,它显示 “使用情况:只显示斑点和非文字”)。计算器显示,如果字体权重为 400 或更大,#2DAD4E 上的白色文字可以在 24px 文字上使用。如果我们想使用 300 字体,那么文字至少应为 41px。当然,这取决于我们使用的字体,而且我们使用的字体与对比度计算器使用的字体也不一样,但这种指导远比 WCAG 2 算法的工具更细致入微。它能帮助我们的团队制定出美观的设计计划。
我们的苗圃网站支持浅色和深色模式,我们的设计师确定 #2DAD4E 可以作为浅色和深色模式的按钮颜色,这对许多用户来说都是可行的,只要他们在设计按钮时仔细考虑字体大小和重量对对比度的影响。但即使考虑到了这些因素,Lc -60.4 对于所有用户来说对比度还是不够,因此对于那些将无障碍首选项设置为要求更高对比度的用户,我们将用两种颜色替换按钮背景色–浅色模式用较深的 #3B873E绿色(白色文本,Lc -76.1),深色模式用较浅的 #77e077绿色(黑色文本,Lc 75.2)。
以下是我们虚构的设计团队希望我们用 CSS 实现的调色板:
当我们在变量中定义颜色时,就可以非常容易地根据这些不同的条件交换颜色值。通过使用 contrast-color(),我们只需担心背景颜色,而不用担心文本颜色的搭配。我们将让浏览器来做这些工作,并免费获得配对的颜色。
要同时完成所有这些工作,我们只需编写这样的代码即可(因为,请记住,我们假装生活在一个更好的算法取代了 CSS 中的 WCAG 2 算法的未来):
--button-color: #2DAD4E; /* brand green background */
@media (prefers-contrast: more) {
@media (prefers-color-scheme: light) {
--button-color: #419543; /* darker green background */
}
@media (prefers-color-scheme: dark) {
--button-color: #77CA8B; /* lighter green background */
}
}
button {
background-color: var(--button-color);
color: contrast-color(var(--button-color));
font-size: 1.5rem; /* 1.5 * 16 = 24px at normal zoom */
font-weight: 500;
}
实际上,由于 WCAG 2 算法是驱动 contrast-color()
的算法,我们可能无法在这个网站上使用它。但如果我们有另一个项目,品牌颜色是深绿色,而白色/黑色之间的选择是正确的,那么它在今天可能会很有帮助。
在为启用/禁用、亮/暗模式、首选对比度等多种状态或选项定义颜色时,使用 contrast-color()
尤其有用。
超越黑白
你可能会想:”但如果我想让浏览器选择的颜色不仅仅是黑/白,那该怎么办呢?如果你在四年前的 Safari 技术预览版 122 中阅读过或试用过我们最初的实现,你可能还记得最初的功能可以做得更多。与最初的 color-contrast()
相比,更新的 contrast-color()
函数大大简化了。
由于关于 WCAG 3 使用哪种颜色对比度算法的决定仍在争论之中,CSS 工作组决定继续使用一种工具,即简单地选择黑色或白色与第一种颜色形成对比。保持简单使得日后更换算法成为可能。通过将选项列表硬编码为黑色/白色,当 WCAG 2 算法被替换时,网站被破坏的可能性就会大大降低,从而为 CSSWG 提供了所需的灵活性,使其能够不断做出必要的改变,即使contrast-color()
已经进入用户手中。
未来,更复杂的工具将会出现,以支持更强大的选项。也许你可以列出一组自定义颜色选项,然后让浏览器从中选择,而不是从黑/白中选择。也许你可以列出一组选项,再指定一个你希望浏览器达到的对比度水平,而不是让浏览器选择能产生最大对比度的选项。
与此同时,在黑白之间进行简单的选择往往就是你所需要的。我们希望尽快将简单的版本提供给您,而不是等待一个需要数年时间的过程。
虽然上面的例子都是在彩色背景上显示黑/白色文字,但contrast-color()
的用途远不止于此。你可以为文字使用自定义颜色,并将背景设为黑/白色。或者完全不涉及文字,为边框、背景等定义颜色。你可以做很多事情。
继续对话
您可以通过阅读创建 APCA(无障碍感知对比度算法)的人员提供的文档,了解有关该算法的更多信息。包括
- APCA 对比度方法简易介绍–以通俗易懂的语言介绍统一感知对比度的方法
- Bronze Simple Mode –“最基本 ”的设计指南,适用于从 WCAG 2 对比度迁移过来的用户。
我们希望听到您对 contrast-color()
的看法。您对该工具的反馈意见将有助于塑造它的未来。您可以在 Bluesky / Mastodon 上找到我,Jen Simmons。或者在 BlueSky,上关注我们的其他网络布道者 Saron Yitbarek,在 Bluesky / Mastodon 上关注 Jon Davis。您还可以在 LinkedIn 上关注 WebKit。
你也许感兴趣的:
- 使用 margin-trim,布局更简便
- 几乎不使用 CSS 的暗色模式
- 了解 CSS 是前端开发的精髓
- 【外评】CSS masonry 砌体布局的替代建议
- 你需要知道的现代 CSS 技巧(2024 年春季版)
- 使用 :has() 作为 CSS 父选择器及其他更多内容
- 一个 Div 能做的事情
- 基于时间的 CSS 动画
- 【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局
- 最漂亮的 CSS 动画背景示例及源代码
针对这个问题,我正在开发一款工具,帮助创建调色板,使颜色对在设计上具有简单、可预测的 WCAG/ACPA 对比度(它在台式机上有更多功能):
https://www.inclusivecolors.com/
因此,一种方法是创建从 100 级(浅色)到 900 级(深色)的不同颜色色板,其中浅度的选择应使所有 700 级颜色与 100 级颜色形成对比,所有 800 级颜色与 200 级颜色形成对比,等等。
这样,您就可以知道红色-700 与灰色-100、绿色-800 与黄色-200 等的对比度,而无需进行检查。
如果进入 “对比度 ”菜单,还可以查看 APCA 算法(旨在更准确)与 WCAG 相比有多严格。特别是对于浅色中的深色,APCA 对于对比度的要求要严格得多,因此您确实不应该在深色主题中使用 WCAG。
此外,如果你进入 “示例 ”菜单,查看 Tailwind 和 IBM Carbon 的调色板,就会发现手工设计的调色板中的色块是如何以非线性的方式改变不同等级的饱和度和色调的。因此,自动挑选白色/黑色对比度是否最佳比较直接(就像文章中提到的那样),但对于更深思熟虑/品牌调色板来说,你不可能只通过简单的明度分量变化来生成颜色,因此这就更具有开放性了。
有一种方法可以使用 LCH 实现与此接近的效果:
来源:https://til.jakelazaroff.com/css/swap-between-black-and-whit…
LCH 太棒了,但 OKLCH 更好!
https://evilmartians.com/chronicles/oklch-in-css-why-quit-rg…
老实说,这篇文章极大地改变了我对这个问题的看法,它是一个非常了不起的工具。我很惊讶我的设计师朋友们竟然完全没有听说过 OKLCH,它解决了一整类的问题。
我从未见过任何 CSS 函数具有这种回调样式,在这种样式中,你可以获得参数,并对其进行修改。太有意思了!还有其他类似的例子吗?
这是 “相对颜色 ”语法,它适用于一系列颜色空间/颜色函数。关键是前面的 “from”。下面是 MDN 文档:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_colors/…
可能会让人感到困惑,但这里的所有内容都是静态参数。前缀–是 css 变量,在 css 声明块中,你可以写:-bg: blue
l “不是!
一些较新的如 calc-size 也是这样的。
lea verou https://lea.verou.me/blog/2024/contrast-color/ 有一篇很好的文章介绍了类似的解决方法
我相信你的说法,因为我在这个手机浏览器组合上确实看到页面加载后变成了白色。
这是对其利弊的一个很好的概述。对于创建简单网站的人来说,这是一种获得适当对比度的可靠而简单的方法。
但是,对于那些需要符合 wcag 标准的生产规模的人来说,我会避免使用这种方法,而是利用适当的语义标记层。语义标记既能加快开发周期,又能保证适当的对比度,在视觉效果上比仅仅将前景层切换为黑色或白色更好。语义标记层的最大优点是非常易于主题化,这意味着您只需花费很少的额外成本就能获得明/暗主题。如果您的品牌颜色是 WCAG2 有问题的颜色之一,您还可以创建单独的 WCAG2 / APCA 可访问主题,这样既能符合要求,又能提供更好的视觉对比选择。
这是我的小众领域专长–我在 Figma 负责变量/标记流,并为 Figma 和 Atlassian 进行过暗色模式植入。我很乐意回答关于标记/主题/可访问颜色的任何问题。
您说的语义标记是什么意思?
正是这种类型的功能让我参与的一个重要项目在 JS 中使用了 CSS(用于相对颜色和对比颜色)。
我很高兴看到这种功能即将出现,并期待它在几年内得到广泛应用。
关于网页上的颜色,语义标记指的是以描述其用途的方式命名的 css 变量,即
* bg-brand (在需要将品牌色作为背景色时使用)
* 文本-危险(可能是红色文本颜色)
* 图标-警告-悬停(可能是深黄橙色,与图标-警告略有不同)
一般来说,标记有三个 “级别”:基本标记、语义标记和组件标记。原始标记描述值。就颜色而言,这可能是一个颜色斜坡。如 red/100、red/200、red/300。语义标记指的是基本标记。例如,bg-brand 的值可能设置为 blue/300。因此,这一层有时也被称为 “引用 ”层,但我并不喜欢这种叫法,因为组件层也会引用语义层。组件层描述了标记在组件中的使用位置,即按钮-bg 或按钮-text。我强烈建议,除了最极端的多品牌情况外,不要使用组件层。如果你不是联合利华,就永远不要使用组件标记。
在设计系统中,不是有很多很多代币命名方案吗?你把它说成是一种普遍做法,是不是有点太超前了?
https://medium.com/eightshapes-llc/naming-tokens-in-design-s…
内森说的是我提到的每个层级中的命名方案,而不是不同的层级。那篇博客详细介绍了语义层和组件层的命名方案。
原始层/语义层/组件层是一种通用做法。它们内部的命名存在很大差异(而且应该存在差异!)。单个标记使用的名称取决于目标和意图–即谷歌材料的语义层使用的命名方案是为丰富多彩的主题而设计的(尽管牺牲了它们应该如何使用的清晰度),而苹果使用的命名方案要简化得多,因为它们的应用程序设计差异要小得多。
不是父辈,但概括是对的。通常有一个基础层(红色/300 等)和一个语义层(.text-danger)。
正如您的链接所涉及的,根据您在上面实施的主题和系统,有无数种不同的方法来实施/扩展这些层。
只有当你不让用户为你的网站设置主题时,这种方法才有效。如果你让用户为你的网站设置主题,那么 OP 的方法会更好用。
我不反对,事实上我完全同意,但最后的 2/3 听起来就像毫无意义的废话,让自己看起来很聪明。我并不是说这不是真的,但这是在吐词。
我喜欢这个功能,但在企业网站/应用程序中,你并不想依赖这个功能,因为你无法控制结果会是怎样。据我所知,WebKit 可能会修复一些错误,或者改变一些东西,从而将结果颜色变成我不想要的颜色。
如果你不理解某些东西,这并不总是吐字不清:)
>但是,在一个大型项目中,有一个庞大的团队,仔细管理这些细节可能会成为一项很难做好的任务。突然间,一个深色按钮上出现了难以辨认的黑色文字,用户不知道该怎么办。
能不能有人在大型项目启动前检查一下按钮?或者,强制规定深色按钮上绝不能有黑色文字,并告诉包括大型项目在内的每个团队成员。
读到关于感知对比度和数学对比度的文章很有意思,我以前不知道。我要把这一点融入到我的工作流程中。
> 能否在大型项目启动前让人看一下按钮?
当然可以,但这就是发布前回归测试周期长达数周甚至数月的原因。一个 “大型项目 ”可能有数千个按钮(甚至更多!),其中许多按钮只有在启用某些设置、在复杂的工作流程中选择某些选项等情况下才能看到。
您可能想了解一下 APCA,因为您可以使用 APCA 算法进行感知对比度计算。
您可以使用 WCAG2 进行对比度计算,APCA 的例子明显掩盖了问题,并导致文章中出现了许多错误的结论(tl;dr:无论采用哪种方法,黑色的对比度都更高,只是 APCA 认为您不需要那么高的对比度,因此您可以使用白色并获得足够的对比度)。
我也知道 WCAG。您也可以直接实现一个检测颜色是否偏暗的函数。这是一个通用函数,例如我的 “isDark ”函数是:“func() < 0.5”(func()省略了,但它是一种算法)。你也可以用“> 0.5 ”来表示 “isLight”。有很多方法可以做到这一点。您可以简单地将十六进制颜色转换为 RGB,然后计算颜色的亮度,再将亮度与阈值(如 0.5)进行比较,将其分为深色或浅色。亮度函数(WCAG 亮度公式)将 RGB 值转换为 0-1 范围,应用伽玛校正,然后使用伽玛校正后的 RGB 值的加权和计算亮度。
> APCA 说您不需要那么大的对比度
如果需要,您可以指定阈值,例如 “apcaContrast(color)) >= $targetContrast”。
其实很简单,只要确保有足够的色彩空间就可以了。
WCAG 亮度公式(色彩科学术语中的相对亮度)的感知中灰为 0.18,而不是 0.5。
关于:只需更改 APCA 对比度目标,这与文章中的 “甚至没有错 ”是分开的。我的意思并不是说 APCA 说你需要更少的对比度是错的,而是说这篇文章认为白色具有更多对比度是错的。
好吧,我用 0.5 作为 0-1 亮度范围的一个方便直观的中点,但这当然是一种简化,与人类的感知并不一致(编辑:是一致的),如果有的话,这更像是一个例子。
你说得没错,0.18 在知觉上确实更接近 “中灰”,因为眼睛对暗色调的反应更敏感,所以,如果我们想识别一种颜色 “感觉 ”是亮还是暗,使用接近 0.18 的阈值更有意义。
也就是说,0.5 是一个数学中点,但正如我所说,它与人类感知亮度的方式并不一致(编辑:它是一致的)。
最终,我们可以使用 0.18-0.3 作为阈值。
> 0-1 亮度范围的中点
亮度有两个物理量,一个是相对亮度,另一个是感知亮度。) 正如您所知道和提到的,在您提到的亮度计算中使用 0.5 来计算相对亮度是错误的(我讨厌迂腐,但这对某些方面很重要,a11y 是许多工作事实上的法律要求,0.5 对于确保 WCAG 2 文字对比度是准确的,只要使用感知亮度 L*)
> 不符合人类的感知
它与人类感知亮度的方式完全一致,事实上,它是一个稳定的工作成果,可以追溯到 20 世纪初。
> 最终,我们可以使用 0.18-0.3 作为阈值
感知亮度和相对亮度都有精确的数学定义,一个可以用另一个来计算。
如果您需要在背景色 C 的情况下达到对比度 K,您就无法将其视为变量。当然,你所说的可变性是有价值的,因为在给定 K 和 C 的情况下,输出会有一个范围,也就是说,如果对比度算法认为你的文字需要 +40 L* 才能达到 APCA/WCAG 的要求,而你的 C 有 50 L*,那么你的调色板就会从 90 L* 到 100 L* 以及 0 L* 到 10 L* 不等。
所以 0.5 还是正确的?我以为我的 0.5 完全错了,我以为它不符合人类的认知,因为我以为我错了。哎哟。我得为自己辩解一下,已经有一段时间了。
顺便问一下,用这种相对简单的方法来判断颜色是否偏深,可行吗?
其中 $threshold 应该是 128 吧?我记得在这种情况下,128 是一个常见的阈值。
我曾经用 0.3R + 0.6G + 0.1B < 128 来计算过,主要是因为我懒得去想更深层次的问题。当然,这并不完美–在有些情况下,相反的黑色或白色对比度会更好–但对于我的目的来说,这已经足够好了(无论背景颜色如何,至少不会让标签无法阅读)。
我实现的东西对比度非常重要,所以我使用了更复杂的算法,不过在某些情况下,你也可以使用不那么复杂的算法。
> 无论从哪个角度看,黑色的对比度都更高
不是吗?博文中的计算器截图非常清楚地显示,根据 APCA,白色的对比度更高。(如果负数令人困惑,您也可以将颜色输入 BridgePCA 计算器,如 https://www.color-contrast.dev/?txtColor=FFFFFF&bgColor=317C… 查看使用 APCA 计算的 WCAG-2 风格 “对比度 ”指标)。
APCA 的目的是使对比度计算在感知上更加准确,而不仅仅是降低阈值。
> APCA 的意义在于使对比度计算在感知上更加准确,而不仅仅是降低阈值。
如果您不幸熟悉数学,那么无论亮度如何(广泛接受的 Y 或 L*,或 APCA 自身的亮度计算),都可以轻而易举地证明它降低了亮度阈值。
关于 “我认为 APCA 的意义在于降低对比度阈值 ”这一观点,你说得完全正确,这只是主要目标的副作用–更准确地建立对比度模型。
根本不存在非感知对比度,感知对比度只是告诉人们东西被重复了。
当我们在做 APCA => BCPA => 声称实际对比度为 2.4 => 查看实际对比度,它是……5.39 时,我们就有点扯远了。
2.4 应该是无法阅读的,但这里显然不是这样。
那么到底是怎么回事呢?
在 BCPA 网站上使用了错误的文字大小,计算结果好像是 12 pt,而文章中是 36 pt。
我认为白色看起来更清晰,但实际上并非如此。我想把蓝色调暗一点,这样就会满意了。
我仍然不相信对比色应该由浏览器供应商来决定,因为它并不总是正确的或可预测的。这会成为所有浏览器的确定性标准吗?相反,这个功能给人的感觉像是一个在设计阶段帮助用户体验团队的工具。
> 这将是一个适用于所有浏览器的确定性标准吗?
文章说该标准规定了使用的计算方法。
我已经感觉到 HDR 显示器、嵌入式设备和其他特殊情况下的一些问题。macOS/iOS 上的标准 Safari 和 Windows/Linux/Android 上的 Chrome 浏览器可能会正确处理。但如果事实证明我是错的,我会非常高兴:)
这里的 “选择 ”是个奇怪的词。有一种计算颜色的算法。
c.f.https://news.ycombinator.com/item?id=44015980,当你删去由于混淆而造成的错误内容时,关于 APCA 按钮的例子,就会更清楚一点,它是 100% 正确的。
而一致性则不然。例如,我们可以想象一个 L* 50 的背景,它与白色或黑色前景的效果是一样的–在这种情况下,美学原则就会发挥作用。
如果对比度 K 和背景色 C 都有深色和浅色可供选择,那么查看 C,如果它的 L* >= 60,则选择浅色。
这样就能达到 100% 的正确性和一致性。
当系统颜色还很酷的时候,我做了一些系统颜色样式。它看起来非常漂亮,但你不知道它们的对比度如何。其中一个叫做 [say] buttonFace,另一个叫做 buttonText,但结果却毫无意义。有人帮我写了一些 js,利用 getComputedStyle 计算对比度。如果无法接受,它就会使用第二种候选颜色,或者通过文本阴影来使文本周围的光环变暗或变亮。
https://i.sstatic.net/18bQt.png
我忘了计算方法,但仔细想想,也许可以取 3 个 RGB 值的平均值进行比较(?
至少,最好能知道 active、focus、hover、link、visited 等伪类的好颜色,以及它们在浅色和深色主题下的各种组合。此外,材质用户界面还增加了禁用、之前、之后等功能。
很久以前,我制作过一个关于类似问题的视频教程–在彩色背景下为文本颜色选择黑色或白色。我的解决方案非常简单。我只是将颜色转换成灰度,然后在黑白之间进行比较。这是一个有趣的项目。不过我不擅长制作视频。
https://youtu.be/tUJvE4xfTgo?si=vFlegFA_7lzijfSR (警告:视频为葡萄牙语)
有趣的是,一位姐妹的评论给出了一个色彩空间公式,可以做到这一点
https://news.ycombinator.com/item?id=44015990
视频看起来不错。我不会说葡萄牙语,所以无法判断你说了什么,但代码看起来不错!
谢谢
你可以选择配色方案中的所有颜色,为什么这比一开始就选择对比鲜明的按钮文字颜色更容易呢?这个功能是为了帮助那些功能不健全的团队,以至于个人可以自由选择不一致的背景色,但同时却无法选择对比鲜明的前景色?
真正需要修复的是在图片或其他不同背景上显示文字(例如,在滚动背景上显示粘性/固定文字),并且需要让文字始终可见的情况。而……这根本无济于事。
因此,这不仅只能(也许)在非常可疑的情况下提供帮助,他们还需要为它设计一个全新的动词,它的功能设置也很贫乏(只能选择黑色或白色),而且他们还采用了最糟糕的对比度选择算法(不能选择感知对比度最大的选项)。该走了!
仅仅因为你没有遇到过该工具有用的情况,就断然否定它,这种做法是有局限性的。
很多网站都允许最终用户选择颜色[1],或根据最终用户提供的资产自动生成颜色。对于那些注重可访问性的网站来说,它们通常会计算对比色,以防止用户创造出非可访问性的体验。希望像这样的内置 CSS 工具能鼓励更多网站提供基本的可访问性,同时也不会妨碍那些希望打造更好体验的网站。
如果这个工具能像 npm contrast-color 软件包一样更容易定制,那就更好了,但博文中详细说明了为什么他们一开始使用白色/黑色,并打算以后改变算法。
[1] Example: https://coolors.co/8fbfe0-7c77b9-1d8a99-0bc9cd-14fff7
是的。我的一个简单用例是让用户创建 “标签”,并为芯片选择自己喜欢的颜色(想想 Github 上的 PR 标签,比如 “good-first-issue”“bugs”,不过是自定义的)。
我很惊讶父母没有遇到过这种用法,我到处都能看到。
> 他们使用了最糟糕的对比度选择算法
他们明确表示,他们遵循的是 WCAG 2 算法,WCAG 3 可能会纠正这个问题。他们说,将来标准化后,他们可以很容易地调整使用更好的算法。
有没有一种在构建时就能完成的好的替代方法?能在 SASS、Tailwind 等之上运行的东西?
这项功能的普及还需要一些时间,而且我对它能否在所有平台上以相同(或正确)的方式实现有些怀疑。
该功能的暂定未来,解决了本主题中的许多问题:
https://drafts.csswg.org/css-color-6/#colorcontrast
最近,我做了一个 500 行的超文本浏览器。然后,我又用 200 行添加了这种自动对比色选择器。在这个过程中,我学到了很多关于色彩空间的知识。
https://akkartik.name/post/2025-04-04-devlog
我的方法有一个不同之处:这是一个创作时的工具。如果没有足够的对比色,就会出错。因此,你必须改变背景,直到有足够的对比色为止。
太酷了 我用 python 和终端颜色手动做了类似的事情 https://calbryant.uk/blog/destroying-the-right-server-with-c…
我记得当年用 YIQ 值做过类似的事情 – https://medium.com/@gkobilansky/a-color-changing-take-on-the…
下面是我收藏的一种方法: https://miunau.com/posts/dynamic-text-contrast-in-css/
>此浏览器不支持 contrast-color()。请在支持该功能的浏览器中尝试此演示,如 Safari 技术预览版
你不需要 “技术预览”,它可以作为普通 Safari 高级设置下的 WebKit 功能标志使用。我只是在手机上启用了它,然后就能查看演示了。
在桌面 Safari(18.2 版 (20620.1.16.11.8)) 功能标志下不可用。
桌面版 Safari 在此可用,我使用的是 18.5 版 (20621.2.5.11.8)。
此后,Safari 已进行了多次安全修复,所以你应该更新:
18.3: https://support.apple.com/en-us/122074
18.3.1: https://support.apple.com/en-us/122285
18.4: https://support.apple.com/en-us/122379
18.5: https://support.apple.com/en-us/122719
此外,18.4 版在标准支持和其他功能方面进行了相当大的更新:
https://webkit.org/blog/16574/webkit-features-in-safari-18-4…
感谢您提供的信息。我已经使用了 “自动更新应用程序和安全响应”,但没有使用完整的 Macos。
我的版本是 18.5 (20621.2.5.11.8),它就在那里。
我在 caniuse.com 上还没有看到这个词条。我猜这是个超新产品。
MDN 甚至还没有它。看来它在一段时间内都是 WebKit 独有的。
CSS 规范添加草案](https://drafts.csswg.org/css-color-5/#resolving-contrast) 刚刚被添加进来。我有点纳闷,为什么 Apple 要在 Safari 中加入 color-contrast,而不是 -webkit-color-contrast,直到其他浏览器至少对该草案表明立场。我所能找到的都是推迟规范的决定(最早可追溯到 2020 年)。
新功能不再使用前缀,任何仍然存在的前缀都是旧的。现在的做法是,在浏览器工作组确定该功能的最终规范之前,将功能标记在功能标志后面进行测试,任何浏览器制造商都可以在公开发布的版本中实现该功能。
https://drafts.csswg.org/css-color-5/#contrast-color
非常新。我认为只有 Safari 浏览器采用了这一技术,即便如此,它仍处于预览阶段。
它在 “Gnome Web ”中运行,而 “Gnome Web ”主要是对 WebKit 的封装。
> 对该功能的支持于 2021 年 3 月在 Safari 技术预览版 122 中首次发布。
https://webkit.org/blog/11577/release-notes-for-safari-techn…
> 已添加对 CSS Color 5 color-contrast() 的实验性支持
https://trac.webkit.org/changeset/273683/webkit/
当然,相对色彩理论色轮可以解决这个问题。
“色轮: 艺术家和设计师的基本色彩理论” https://dessign.net/color-wheel-theory/
遗憾的是,它还不能在 Firefox 上运行 🙁
TLDR:”此浏览器不支持 contrast-color()。请在支持对比度-颜色()的浏览器中尝试此演示,如 Safari 技术预览版”。
这篇文章错了:
– 他们的工作确实确保了对比度。
– 蓝底白字的对比度显然更低,而不是更高。(眯眼是一种低成本的测试方法,或者从显示器向后走)。
使用 APCA 时,L* 60 左右的背景仍倾向于使用白色前景,这在美学上更接近眼睛的需求。
无论如何,即使使用 APCA,黑色前景的对比度也会更高。
平心而论,APCA 几乎总是以这种方式来证明其优于长期使用的标准,因此人们的前提是 APCA 的演示图像具有更高的对比度,而不是 “我们说白色前景具有足够的对比度,即使它也说黑色前景的对比度会更高”。
(来源:2020 年,围绕相同的科学建立了色彩系统,实现了最新的材料主题迭代)
> 蓝底白字的对比度显然更低,而不是更高。
是你的屏幕真的严重失准,还是你的视力有什么异常?我只能想到这些。我同意文章的观点,白色的对比度显然更高。
> 无论如何,黑色前景的对比度都会更高,即使使用 APCA 也是如此。
好吧,现在我真是一头雾水。文章显示了白色和黑色在特定蓝色上的明度对比:黑色的 Lᶜ 为 38.7,白色的 Lᶜ 为 -70.9。根据 APCA,白色前景的对比度更高。
我真的对你说的话感到困惑,因为这听起来都很连贯……只不过都是从后往前看的。
我能想到的唯一解释是,GP 有点同义反复地将对比度定义为 “WCAG 2 计算对比度的公式所返回的值”(可能是假设 WCAG 2 的 “科学 ”比实际更有现实基础)。
我不能对 “材料您 ”说三道四,但我在一些公司看到过这种想法,这些公司更关注的是是否符合 WCAG 2 的严格措辞,而不是实际的用户体验。人们甚至可以学会忽略自己的眼睛,相当准确地猜出一对给定颜色的 WCAG 2 “对比度 ”指标是多少,而与颜色之间的难易程度无关。
希望 WCAG 3 能够纳入 APCA 等机构提供的更好的色彩指导,至少这些公司不要再总是生产无法辨认的黑底按钮和徽章了。
投票者,我很高兴得到反馈,我很惊讶它是 -3。
编辑:
我明白了,这很容易被解读为 “整篇文章都是错的”,而不是 “这篇文章在这几点上是错的”。
您可以自由阐述您的担忧。我们可以把这个问题上升到对话的层面,我觉得这样对我们双方都好,而不是我把那句话当成是针对我个人的。
例如,我同意容器的主色不应该是 L* 90,不应该用于按钮,也不应该严格限制色度。事实上,我就是因为这个原因离开的,因为副总裁们不明白为什么我们第一天就没有这个功能,他们反复批准修复,而安卓系统的功能障碍让对话一直停留在 “什么?工程部的人什么也没说!总之,锁屏时钟!”
我没有投票,但 “你的文章是错的 ”这句话忽略了整篇文章,也忽略了对 “纯数字对比度越大,对比度就越大 ”的详细解释。
> 2020 年,谷歌围绕同样的科学建立了色彩系统,实现了最新迭代的材料主题化
难怪包括 Material 在内的所有谷歌产品都会在对比度方面出现问题。