如何根据背景颜色决定字体颜色为白色或黑色?
我想显示一些像这个例子的图像
填充颜色由数据库中带有颜色的字段决定以十六进制表示(例如:ClassX -> 颜色:#66FFFF)。 现在,我想在填充上方显示所选颜色的数据(如上图所示),但我需要知道颜色是深色还是浅色,这样我就知道单词应该是白色还是黑色。 有办法吗? tks
I want to show some images like this example
The fill color is decided by a field in the data base with the color in hex (ex:ClassX -> Color: #66FFFF).
Now, I want to show data above a fill with the selected color (like in the image above) but i need to know if the color is dark or light so i know if the words should be in white or black.
Is there a way? tks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(27)
基于我的对类似问题的回答。
您需要将十六进制代码分成 3 部分才能获得单独的红色、绿色和蓝色强度。代码的每 2 位数字代表一个十六进制(基数 16)表示法的值。我不会在这里详细介绍转换的细节,它们很容易查找。
一旦获得了各个颜色的强度,您就可以确定颜色的整体强度并选择相应的文本。
186 的阈值是基于理论的,但可以根据口味进行调整。根据评论,低于 150 的阈值可能更适合您。
编辑:上面的代码很简单,而且工作得相当好,并且似乎在 StackOverflow 上得到了很好的接受。然而,下面的评论之一表明,在某些情况下,它可能会导致不遵守 W3C 准则。在此,我得出了一种修改后的形式,该形式始终根据指南选择最高对比度。如果您不需要需要遵守 W3C 规则,那么我会坚持使用上面更简单的公式。要深入了解此问题,请参阅对比度数学和相关视觉问题。
W3C 建议 (WCAG 2.0) 中给出的对比公式为
(L1 + 0.05) / (L2 + 0.05)
,其中L1
是最亮颜色的亮度,L2
是最暗颜色的亮度,范围为 0.0- 1.0。黑色的亮度为 0.0,白色的亮度为 1.0,因此替换这些值可以让您确定对比度最高的值。如果黑色的对比度大于白色的对比度,则使用黑色,否则使用白色。假设您正在测试的颜色的亮度为L
,则测试将变为:这在代数上简化为:
或近似为:
剩下的唯一事情就是计算
L
。该公式也在指南中给出,它看起来像是从 sRGB 到线性的转换RGB 后跟 ITU-R 建议 BT.709亮度。阈值 0.179 不应更改,因为它与 W3C 准则相关。如果您发现结果不符合您的喜好,请尝试上面更简单的公式。
Building on my answer to a similar question.
You need to break the hex code into 3 pieces to get the individual red, green, and blue intensities. Each 2 digits of the code represent a value in hexadecimal (base-16) notation. I won't get into the details of the conversion here, they're easy to look up.
Once you have the intensities for the individual colors, you can determine the overall intensity of the color and choose the corresponding text.
The threshold of 186 is based on theory, but can be adjusted to taste. Based on the comments below a threshold of 150 may work better for you.
Edit: The above is simple and works reasonably well, and seems to have good acceptance here at StackOverflow. However, one of the comments below shows it can lead to non-compliance with W3C guidelines in some circumstances. Herewith I derive a modified form that always chooses the highest contrast based on the guidelines. If you don't need to conform to W3C rules then I'd stick with the simpler formula above. For an interesting look into the problems with this see Contrast Ratio Math and Related Visual Issues.
The formula given for contrast in the W3C Recommendations (WCAG 2.0) is
(L1 + 0.05) / (L2 + 0.05)
, whereL1
is the luminance of the lightest color andL2
is the luminance of the darkest on a scale of 0.0-1.0. The luminance of black is 0.0 and white is 1.0, so substituting those values lets you determine the one with the highest contrast. If the contrast for black is greater than the contrast for white, use black, otherwise use white. Given the luminance of the color you're testing asL
the test becomes:This simplifies down algebraically to:
Or approximately:
The only thing left is to compute
L
. That formula is also given in the guidelines and it looks like the conversion from sRGB to linear RGB followed by the ITU-R recommendation BT.709 for luminance.The threshold of 0.179 should not be changed since it is tied to the W3C guidelines. If you find the results not to your liking, try the simpler formula above.
我不相信这段代码,因为它不是我的,但我把它留在这里供其他人将来快速找到:
基于 Mark Ransoms 的回答,这里是简单版本的代码片段:
这是高级版本的代码片段:
要使用它们,只需致电:
另外,感谢
Alx
和chetstone
。I take no credit for this code as it's not mine, but I leave it here for others to find quickly in the future:
Based on Mark Ransoms answer, here's a code snippet for the simple version:
and here's the code snippet for the advanced version:
To use them just call:
Also, thanks
Alx
andchetstone
.除了算术解决方案之外,还可以使用人工智能神经网络。优点是您可以根据自己的品味和需求对其进行定制(即,明亮饱和红色上的灰白色文本看起来不错,并且与黑色一样可读)。
这是一个简洁的 Javascript 演示,它阐释了这个概念。您还可以在演示中生成您自己的 JS 公式。
https://harthur.github.io/brain/
下面是一些帮助我理清思路的图表
Additionally to the arithmetic solutions, it's also possible to use an AI neural network. The advantage is that you can tailor it to your own taste and needs (ie. off-white text on bright saturated reds looks good and is just as readable as black).
Here's a neat Javascript demo that illustrates the concept. You can also generate your own JS formula right in the demo.
https://harthur.github.io/brain/
Below are some charts that helped me get my mind around the problem.
In the first chart, lightness is a constant 128, while hue and saturation vary. In the second chart, saturation is a constant 255, while hue and lightness vary.
这个(JavaScript 代码)怎么样?
How about this (JavaScript code)?
如果您像我一样正在寻找一款考虑 Alpha 的 RGBA 版本,那么这里是一个非常适合高对比度的版本。
If like me you were looking for a RGBA version that takes alpha into account, here is one that works really well to have high contrast.
这是我自己的方法,我一直在使用,到目前为止还没有遇到问题
Here's my own method that I've been using and haven't had a problem with so far ????
这是我在 Android 上的 Java 解决方案:
Here is my solution in Java for Android:
根据 @MarkRansom 的回答,我创建了一个 PHP 脚本,您可以在这里找到:
Based on the answer of @MarkRansom, I created a PHP script you can find here:
这是 Mark Ransom 答案的快速版本,作为 UIColor 的扩展
This is a swift version of Mark Ransom's answer as an extension of UIColor
我基于@SudoPlz提出的高级功能做了一个功能,该功能还考虑了浅色和深色:
因此,如果深色文本不是黑色而是栗色,则灰色背景上推荐的文本颜色将变为白色:
I did a function based on the advanced one proposed by @SudoPlz which takes also account of light and dark colors:
Therefore if the dark text is not black but maroon, the recommended text color on a grey background becomes white:
这是 Mark Ransom 答案的 R 版本,仅使用基本 R。
This is an R version of Mark Ransom's answer, using base R only.
我正在使用 tinyColor 库,它也可以完成这项工作。
此方法还接受 rgb 颜色,例如
rgb(102,255,255)
I'm using the tinyColor library which can also do the job.
This method would also accept rgb color like
rgb(102,255,255)
这只是一个在单击元素时更改 SVG 复选标记颜色的示例。它将根据单击元素的背景颜色将复选标记颜色设置为黑色或白色。
https://gist.github.com/dcondrey/183971f17808e9277572
This is just an example that will change the color of an SVG checkmark when clicking on an element. It will set the checkmark color to black or white based on the background-color of the clicked element.
https://gist.github.com/dcondrey/183971f17808e9277572
我使用此 JavaScript 函数将
rgb
/rgba
转换为'white'
或'black'
。您可以输入任何这些格式,它将输出
'black'
或'white'
rgb(255,255,255)
rgba(255,255,255, 0.1)
颜色:rgba(255,255,255,0.1)
255,255,255,0.1
I use this JavaScript function to convert
rgb
/rgba
to'white'
or'black'
.You can enter any of these formats and it will output
'black'
or'white'
rgb(255,255,255)
rgba(255,255,255,0.1)
color:rgba(255,255,255,0.1)
255,255,255,0.1
马克的详细答案效果很好。下面是 javascript 中的实现:
然后可以调用此函数
lum([111, 22, 255])
来获得白色或黑色。Mark's detailed answer works great. Here is an implementation in javascript:
Then can call this function
lum([111, 22, 255])
to get white or black.我从来没有做过这样的事情,但是编写一个函数来根据十六进制 7F (FF / 2) 的中值颜色检查每种颜色的值怎么样?如果三种颜色中的两种大于 7F,则您正在使用较暗的颜色。
I've never done anything like this, but what about writing a function to check the values of each of the colors against the median color of Hex 7F (FF / 2). If two of the three colors are greater than 7F, then you're working with a darker color.
LESS 有一个很好的
contrast()
函数,对我来说效果很好,请参阅 http://lesscss.org/functions/#color-operations-contrast“选择两种颜色中哪种颜色与另一种颜色的对比度最大。
这对于确保颜色在背景下可读非常有用,这对于可访问性合规性也很有用。此函数的工作方式与 Compass for SASS 中的对比函数相同。根据 WCAG 2.0,使用伽马校正亮度值而不是亮度来比较颜色。”
示例:
输出:
LESS has a nice
contrast()
function that worked nicely for me, see http://lesscss.org/functions/#color-operations-contrast"Choose which of two colors provides the greatest contrast with another.
This is useful for ensuring that a color is readable against a background, which is also useful for accessibility compliance. This function works the same way as the contrast function in Compass for SASS. In accordance with WCAG 2.0, colors are compared using their gamma-corrected luma value, not their lightness."
Example:
Output:
从十六进制到黑色或白色:
From hex to black or white:
基于链接中的不同输入根据背景将前景色设为黑色或白色< /a> 和这个线程,我为 Color 创建了一个扩展类,为您提供所需的对比色。
代码如下:
Based on different inputs from the link Make foregroundcolor black or white depending on background and this thread, I made an extension class for Color that gives you required contrast colors.
The code goes as below:
使用
androidx.compose.ui.graphics.Color
时,接受的答案在 Android 上从未起作用。然后我发现 Android Jetpack Compose 中实际上内置了luminance()
函数,它返回 [0,1] 之间的亮度值。文档称“基于 WCAG 2.0、W3C 建议 2008 年 12 月 11 日定义的相对亮度公式。”。这是 官方源代码。
用法示例:
Accepted answer somehow never worked on Android when using
androidx.compose.ui.graphics.Color
. Then i found there is actually built inluminance()
function in Android Jetpack Compose which returns luminance value between [0,1]. Documentation says "Based on the formula for relative luminance defined in WCAG 2.0, W3C Recommendation 11 December 2008.".Here is the official source code.
Example usage:
@SoBiT,我正在看你的答案,看起来不错,但其中有一个小错误。您的函数 hexToG 和 hextoB 需要进行少量编辑。 substr 中的最后一个数字是字符串的长度,因此在本例中它应该是“2”,而不是 4 或 6。
@SoBiT, I was looking at your answer, which looks good, but there is a small mistake in it. Your function hexToG, and hextoB need a minor edit. The last number in substr is the length of the string, and so in this case itshould be "2", rather than 4 or 6.
基于 Mark 的回答的 iOS Objective-c 版本代码:
Objective-c version code for iOS based on Mark's answer:
使用所有 24 位颜色进行测试怎么样?
请注意,YIQ 方法将返回 1.9:1 的最小对比度,这不能通过 AA 和 AAA WCAG2.0 测试(假设阈值为 128)。
对于W3C方法,它将返回4.58:1的最小对比度,即通过大文本的AA和AAA测试,以及小文本的AA测试,但不会通过每种颜色的小文本的AAA测试。
What about testing with all 24 bits colors ?
Be aware that YIQ method will return a minimum contrast ratio of 1.9:1, that doesn't pass AA and AAA WCAG2.0 tests, assuming a 128 threshold.
For W3C method, it will return a minimum contrast ratio of 4.58:1, that pass AA and AAA tests for large text, and AA test for small text, it won't pass AAA test for small text for every colors.
这是我的 Java Swing 代码,基于 Mark 的惊人答案:
Here is my code for Java Swing based on Mark's amazing answer:
以防万一有人关心 Mark Ransom 答案的
SCSS
版本:Just in case anybody cares for a
SCSS
version of Mark Ransom's answer:基于@SudoPlz 答案的 Ruby 解决方案
Ruby solution based on @SudoPlz's answer
对于任何搜索
SudoPlz的高级功能:
依赖于
For anyone searching for a Python3 implementation of
SudoPlz's advanced function:
Which depends on
hex_to_rgb
from this venerable question.