hwb()

Baseline 广泛可用 *

此功能已经非常成熟,可在多种设备和浏览器版本上使用。自 2022 年 4 月以来,它已在各大浏览器中得到支持。

* 此特性的某些部分可能存在不同级别的支持。

hwb() 函数式表示法根据颜色的色相、白度和黑度在 sRGB 色彩空间中表示一种颜色。一个可选的 Alpha 分量表示颜色的透明度。

试一试

background: hwb(12 50% 0%);
background: hwb(50deg 30% 40%);
background: hwb(0.5turn 10% 0% / 0.5);
background: hwb(0 100% 0% / 50%);
<section id="default-example">
  <div class="transition-all" id="example-element"></div>
</section>
#example-element {
  min-width: 100%;
  min-height: 100%;
  padding: 10%;
}

语法

css
/* Absolute values */
hwb(194 0% 0%)
hwb(194 0% 0% / .5)

/* Relative values */
hwb(from green h w b / 0.5)
hwb(from #123456 h calc(w + 30) b)
hwb(from lch(40% 70 240deg) h w calc(b - 30))

描述

sRGB 色彩空间中,这个颜色函数由一个 <hue> 角度值、一个白度值、一个黑度值,以及一个可选的表示颜色透明度的 Alpha 值定义。

特定色相所对应的角度在 sRGB(被 hsl()hwb() 使用)、CIELAB(被 lch() 使用)和 Oklab(被 oklch() 使用)色彩空间中是不同的。hwb()hsl() 处于相同的色彩空间,因此具有相同的色相角度。更多细节和示例请参阅 <hue> 参考页面,或者尝试在颜色选择器上改变色相来观察实际效果。

当一个 hwb() 颜色的白度(W)和黑度(B)值都为 0 时,它是完全饱和的。对于任意色相值 Hhwb(H 0% 0%)hsl(H 100% 50%) 是相同的颜色。增加白度值会使颜色变亮。增加黑度值会使颜色变暗。

当黑度和白度都大于 0 时,颜色会变得柔和,趋向于灰色。当白度和黑度的总和等于或大于 100% 时——换句话说,如果 W + B >= 100%,该颜色函数会定义一种灰色。当两个值的总和大于 100% 时(W + B > 100%),灰色颜色的白度和黑度值会被有效地归一化为 W / (W + B)B / (W + B)

下面描述了绝对颜色和相对颜色的允许值。

绝对值语法

hwb(H W B[ / A])

参数如下:

H

一个 <number>、一个 <angle> 或关键字 none(在此情况下等同于 0deg),表示颜色的<hue>(色相)角度。

W

一个表示颜色白度的 <percentage>,或关键字 none(在此情况下等同于 0%),用于混入。0% 表示没有白度。如果 B0100% 表示完全的白度,否则 WB 的值都会被归一化。

B

一个表示颜色黑度的 <percentage>,或关键字 none(在此情况下等同于 0%),用于混入。0% 表示没有黑度。如果 W0100% 表示完全的黑度,否则 WB 的值都会被归一化。

A 可选

一个 <alpha-value>,表示颜色的 alpha 通道值,其中数字 0 对应 0%(完全透明),1 对应 100%(完全不透明)。此外,关键字 none 可用于明确指定无 alpha 通道。如果未明确指定 A 通道值,则默认为 100%。如果包含该值,则其前面需要有一个斜杠(/)。

备注:有关 none 的效果,请参阅缺失的颜色分量

备注: 绝对 hwb() 颜色会被序列化为 rgb() 值。红色、绿色和蓝色分量的值在序列化时可能会被四舍五入。

相对值语法

hwb(from <color> H W B[ / A])

参数如下:

from <color>

在定义相对颜色时,总是包含关键字 from,其后跟着一个 <color> 值,表示源颜色。这是相对颜色所基于的原始颜色。源颜色可以是任何有效的 <color> 语法,包括另一个相对颜色。

H

一个 <number>、一个 <angle> 或关键字 none(在此情况下等同于 0deg),表示输出颜色的 <hue> 角度。

W

一个表示颜色白度的 <percentage>,或关键字 none(在此情况下等同于 0%),用于混入。0% 表示没有白度。如果 B0100% 表示完全的白度,否则 WB 的值都会被归一化。

B

一个表示颜色黑度的 <percentage>,或关键字 none(在此情况下等同于 0%),用于混入。0% 表示没有黑度。如果 W0100% 表示完全的黑度,否则 WB 的值都会被归一化。

A 可选

一个 <alpha-value>,表示输出颜色的 alpha 通道值,其中数字 0 对应 0%(完全透明),1 对应 100%(完全不透明)。此外,关键字 none 可用于明确指定无 alpha 通道。如果未明确指定 A 通道值,则默认为源颜色的 alpha 通道值。如果包含该值,则其前面需要有一个斜杠(/)。

备注: 为了完全支持表示可见颜色的全部光谱,相对 hwb() 颜色函数的输出会被序列化为 color(srgb)。这意味着通过 HTMLElement.style 属性或 CSSStyleDeclaration.getPropertyValue() 方法查询输出的颜色值,将返回一个 color(srgb ...) 形式的颜色值。

定义相对颜色输出通道分量

hwb() 函数内部使用相对颜色语法时,浏览器会将源颜色转换为等效的 HWB 颜色(如果尚未指定为 HWB)。该颜色被定义为三个不同的颜色通道值——h(色相)、w(白色)和 b(黑色)——外加一个 Alpha 通道值(alpha)。这些通道值在函数内部可用,用于定义输出颜色的通道值。

  • h 通道值解析为一个介于 0360(含)之间的 <number>
  • wb 通道各自解析为一个介于 0100 之间(包含 0 和 100)的 <number>
  • alpha 通道值解析为一个介于 01(含)之间的 <number>

在定义相对颜色时,输出颜色的不同通道可以用几种不同的方式表示。下面,我们将通过一些示例来说明这些方式。

在下面的前两个示例中,我们使用了相对颜色语法。然而,第一个示例输出与源颜色相同的颜色,而第二个示例输出的颜色完全不基于源颜色。它们并没有真正创建相对颜色!你不太可能在实际的代码库中使用它们,而可能会直接使用绝对颜色值。我们包含这些示例是为了作为学习相对 hwb() 语法的起点。

让我们从源颜色 hsl(0 100% 50%)(等同于 hwb(0 0% 0%))开始。下面的函数输出与源颜色相同的颜色——它使用源颜色的 hwb 通道值(分别为 00%0%)作为输出通道值。

css
hwb(from hsl(0 100% 50%) h w b)

此函数的输出颜色是 hwb(0 0% 0%) 的 sRGB color() 等效值:color(srgb 1 0 0)

下一个函数对输出颜色的通道值使用绝对值,输出了一个完全不同于源颜色的新颜色:

css
hwb(from hsl(0 100% 50%) 240 52% 12%)

在上述情况中,输出颜色是 hwb(240 52% 12%) 的 sRGB color() 等效值:color(srgb 0.52 0.52 0.88)

以下函数创建了一个基于源颜色的相对颜色:

css
hwb(from hsl(0 100% 50%) h 30% b)

此示例:

  • 将源颜色(hsl(0 100% 50%))转换为 hwb() 等效值(hwb(0 0% 0%))。
  • 将输出颜色的 HB 通道值设置为源颜色 hwb() 等效值的 HB 通道值——这些值分别为 00%
  • 将输出颜色的 W 通道值设置为一个不基于源颜色的新值:30%

最终的输出颜色是在 sRGB 色彩空间中等同于 hwb(0 30% 0%) 的颜色——color(srgb 1 0.3 0.3)

备注: 如上所述,如果输出颜色使用的颜色模型与源颜色不同,源颜色会在后台被转换为与输出颜色相同的模型或空间,以便以兼容的方式(即使用相同的通道)表示。

在本节我们目前看到的示例中,源颜色和输出颜色的 alpha 通道都没有被明确指定。当未指定输出颜色的 alpha 通道时,它默认为与源颜色 alpha 通道相同的值。当未指定源颜色的 alpha 通道时(且它不是相对颜色),它默认为 1。因此,上述示例中的源和输出 alpha 通道值均为 1

让我们看一些指定源和输出 alpha 通道值的示例。第一个示例将输出 alpha 通道值指定为与源 alpha 通道值相同,而第二个示例则指定一个与源 alpha 通道值无关的不同输出 alpha 通道值。

css
hwb(from hsl(0 100% 50% / 0.8) h w b / alpha)
/* Computed output color: color(srgb 1 0 0 / 0.8) */

hwb(from hsl(0 100% 50% / 0.8) h w b / 0.5)
/* Computed output color: color(srgb 1 0 0 / 0.5) */

在下面的示例中,hsl() 源颜色再次被转换为 hwb() 表示——hwb(0 0% 0%)calc() 计算被应用于 HWBA 值,最终的输出颜色是在 sRGB 色彩空间中等同于 hwb(120 25% 10% / 0.9 的颜色:color(srgb 0.25 0.9 0.25 / 0.9)

css
hwb(from hsl(0 100% 50%) calc(h + 120) calc(w + 25) calc(b + 10) / calc(alpha - 0.1))

备注:因为源颜色通道值被解析为 <number> 值,所以在使用它们进行计算时,你必须给它们加上数字,即使在通道通常接受 <percentage><angle> 或其他值类型的情况下也是如此。例如,将 <percentage> 添加到 <number> 是行不通的。

正式语法

<hwb()> = 
hwb( [ from <color> ]? [ <hue> | none ] [ <percentage> | <number> | none ] [ <percentage> | <number> | none ] [ / [ <alpha-value> | none ] ]? )

<hue> =
<number> |
<angle>

<alpha-value> =
<number> |
<percentage>

示例

使用 hwb() 的相对颜色

此示例为三个 <div> 元素设置了不同的背景颜色。中间的元素使用了未经修改的 --base-color,而左右两边的元素则使用了该 --base-color 的提亮和变暗版本。

这些变体是使用相对颜色定义的——--base-color 自定义属性被传入一个 hwb() 函数,然后通过 calc() 函数修改输出颜色的白色和黑色通道以达到预期效果。亮色变体在白色通道上增加了 30%,而暗色变体在黑色通道上增加了 30%。

CSS

css
:root {
  --base-color: orange;
}

/* As per the spec, w and b values should resolve to a number between 0-100
   However, Chrome 121+ incorrectly resolves them to numbers between 0-1
   hence currently using calculations like w + 0.3 instead of w + 30 */

#one {
  background-color: hwb(from var(--base-color) h calc(w + 0.3) b);
}

#two {
  background-color: var(--base-color);
}

#three {
  background-color: hwb(from var(--base-color) h w calc(b + 0.3));
}

/* Use @supports to add in support for old syntax that requires % units to
   be specified in w and b calculations. This is required for Safari 16.4+. */
@supports (color: hwb(from red h w calc(b + 30%))) {
  #one {
    background-color: hwb(from var(--base-color) h calc(w + 30%) b);
  }

  #three {
    background-color: hwb(from var(--base-color) h w calc(b + 30%));
  }
}

结果

输出如下:

规范

规范
CSS 颜色模块第五版
# relative-HWB
CSS 颜色模块第四版
# the-hwb-notation

浏览器兼容性

另见