CSS 颜色设置透明度的新姿势

发布于 大漠

在 CSS 中,我们有很多种方式为元素设置透明度,常见的是给元素设置透明度和给颜色设置透明度,不同的方式将会带来不一样的效果。那么今天,我们就一起来聊聊 CSS 中的不透明度。感兴趣的同学,请继续往下阅读。

设计中的透明度

我们先从设计中开始。就拿 Figma 这样的设计软件来举例。设计师在给一个对象设置透明度,往往会有以下几种方式:

这两种方式中,第一种就是给整个对象(或图层)设置 opacity ,即:

.element {
    background: #D9D9D9;
    opacity: 0.5;
}

第二种是给元素背景颜色设备透明度,例如:

.element {
    background: rgb(217  217 217 / 0.5);
}

它们不同之处是,opacity 属性会将整个元素设备透明度,包括它的所有 UI 样式,比如背景颜色(background-color)、文本颜色(color)和边框(border)等。而 rgb() 只是调整背景颜色的透明度。

从这一点而言,如果我们要给元素的 UI 颜色设置透明度时,不应该使用 opacity 属性,更应该使用带有透明度的颜色值。

给颜色设置透明度

在 CSS 中,可以用于设置颜色的函数有很多种,比如我们熟悉的 rgb()hsl() ,包括后面新出的颜色函数 hwb()lab()lch()oklab()oklch() 等,都可以显式指定透明通道的值。例如:

:root {
    --opacity-in-rgb: rgb(0 0 0 / .5);
    --opacity-in-hsl: hsl(0deg 0% 0% / 50%);
    --opacity-in-hwb: hwb(0deg 0% 100% / 50%);
    --opacity-in-lab: lab(0 0 0 / 0.5);
    --opacity-in-lch: lch(0 0 0 / 0.5);
    --opacity-in-oklab: oklab(0 0 0 / 0.5);
    --opacity-in-oklch: oklch(0 0 0 / 0.5);
    --opacity-in-color: color(display-p3 0 0 0 / 0.5);
}

包括十六进制 HEX 的颜色,也可以用来描述带有透明度的颜色,例如:

:root {
    --opacity-in-hex: #00000080;
}

但它们有一个共同的特性,那就需要知道各个颜色函数对应的颜色通道的值。这是一个极为不方便的地方。换句话说,如果有一种方式,可以将一个颜色直接转换成带有透明通道的颜色值,对于 Web 开发者是不是要方便的多。假设你的品牌色是一个十六进制的颜色(比如, #09face),现在你需要给该颜色添加 50% 的透明度。按照以往的方式,你需要知道 0% ~ 100% 之间对应的十六进制硬编码,或者将十六进制转换为其他描述颜色的函数,例如 rgb()hsl() 等。

庆幸的是,CSS 新增的一些颜色函数功能,可以让事情变得简单地说。比如相对颜色、混合颜色等。

相对颜色

我个人更喜欢相对颜色的语法。使用此语法,你只需要在相应的颜色函数中使用 from 关键词,该关键词可以为你解构颜色模型,以便你可以在该颜色模型中调整颜色,比如设置颜色透明度:

:root {
    --brand-color: #09face;
}

.element {
    color: rgb(from var(--brand-color) r g b / 50%);
    color: hsl(from var(--brand-color) h s l / 50%);
    color: hwb(from var(--brand-color) h w b / 50%);
    color: lch(from var(--brand-color) l c h / 50%);
    color: lab(from var(--brand-color) l a b / 50%);
    color: oklab(from var(--brand-color) l a b / 50%);
    color: oklch(from var(--brand-color) l c h / 50%);
}

Demo 地址:https://codepen.io/airen/full/KKrPPYe (请使用 Safari 浏览器查看)

在上面的示例中,我使用了十六进制来描述品牌色,并应用了 50% 的透明度。在所有颜色模型中,结果都相同。我认为这看起来很好。

不幸的是,相对颜色语法到目前为止(写这篇文章时)也只得到了 Safari 浏览器的支持。

更为有意思的是,颜色相对语法还可以使用 calc() 函数,对颜色各个部分进行调整,例如:

.add-opacity {
    --original-collor: #09face;

    background: rgb(from var(--original-collor) r g b / 50%);
    background: hsl(from var(--original-collor) h s l / 50%);
    background: oklch(from var(--original-collor) l c h / 50%);
    background: hwb(from var(--original-collor) h w b / 50%);
    background: lab(from var(--original-collor) l a b / 50%);
    background: lch(from var(--original-collor) l c h / 50%);
} 

Demo 地址:https://codepen.io/airen/full/jOevEeB (请使用 Safari 浏览器查看)

CSS color-mix() 函数

有意思的是,CSS 的 color-mix() 也可以用来调整颜色的不透明度。假设你要创建品牌颜色的半透明版本,你可以使用 transparent 与品牌色混合,并起调整 transparent (透明颜色)的混合比例。它看起来有点像这样:

:root {
    --brand-color: #8832CC;
    
    --brand-color-a10: color-mix(in oklch, var(--brand-color), transparent 90%);
    --brand-color-a20: color-mix(in oklch, var(--brand-color), transparent 80%);
    --brand-color-a30: color-mix(in oklch, var(--brand-color), transparent 70%);
    --brand-color-a40: color-mix(in oklch, var(--brand-color), transparent 60%);
    --brand-color-a50: color-mix(in oklch, var(--brand-color), transparent 50%);
    --brand-color-a60: color-mix(in oklch, var(--brand-color), transparent 40%);
    --brand-color-a70: color-mix(in oklch, var(--brand-color), transparent 30%);
    --brand-color-a80: color-mix(in oklch, var(--brand-color), transparent 20%);
    --brand-color-a90: color-mix(in oklch, var(--brand-color), transparent 10%);
}

Demo 地址:https://codepen.io/airen/full/eYPXPrZ

通过这种方式使用 color-mix 函数,你可以保留品牌颜色的同时还可以进行透明度的调整。同样,相对颜色语法确实是为此而设计的,但是使用 color-mix() 也很酷。

小结

CSS 的相对颜色和 color-mix() 都是 CSS 颜色的新特性,在这里我们利用这些新特性,帮助我们更好的给颜色设置透明度。