它不是一个颜色
浏览器画半透明的东西,走的是 CSS Compositing 里那条 source-over 公式:
成色 = 前景 × α + 底色 × (1 − α)
三个通道各算一遍,直接在 0 到 255 的编码值上算,不先解 gamma。所以
rgba(0,0,0,.6) 压在白底上是 ,
对白底 ;同一层压在
#fafafa 的卡片底上就成了 。
差得不多,是因为白和 #fafafa 本来就差得不多。压到图片上、压到品牌色上,就没数了。
α 不是令牌。成色才是令牌。
动手
左边浅色底,右边深色底,同一个 α。拖一下看成色和对比度怎么走, 底下那行「过 4.5 至少 α」是反算出来的:要过正文线,这层字最少得多不透明。
半透明的字压在两种底上
三种常见用法,三种判法
次要文字
color: rgba(0,0,0,.6) 这种写法是想要「淡一点的字」。淡一点没问题,
问题是它一进卡片就换了个色,一上图片就没法算。把成色写成实色,
浅色一个值,深色一个值,两个都过线,就完了。
黑字压白要过 4.5:1,α 至少 。
遮罩层
弹层后面那块半透明黑,目标正好相反:要让下面的内容退下去。 这时候要问的不是「够不够对比度」,是「下面的字还看不看得清」。 下面的内容被压到 Lc 30 以下、比值 1.5 以内,才算真的退下去了。 把上面演示里的字色换成页面文字色、α 调到遮罩的值,读那个数就行。
禁用态
不能用 opacity。禁用的按钮半透明叠在不同底上,成色不可控, 对比度无法保证;而且 opacity 会把按钮里的字、边框、图标一起冲淡,三样东西各掉各的。 禁用态该砍色度再拉向背景,用一个实色。配色工作台会把这个色算出来。
深色下
同一个 α 在两套主题下不是同一种效果。白字 60% 压在 #101116 上是
,对底 ;
黑字 60% 压白是 。数字差不多,
APCA 会告诉你深底浅字实际更吃力,这是
另一篇讲的事。
所以深色那套不是「把 α 抄过去」,是各自算各自的成色。
上面导出的 CSS 已经是两套实色,深色规则成对写好了。
口径。成色按 CSS Compositing 1 的 source-over 在 sRGB 编码值上算,
跟浏览器默认渲染一致。color-mix(in oklab, …) 是另一回事,那是在 Oklab 里混,
结果不同,这里不算它。对比度两个口径一起给:WCAG 2.1 是现行规范,
APCA 是 WCAG 3 草案,谁也不替谁。