4 ms·
Calculating Color Contrast for Legible Text in Ruby
- bradleyland 16y agoWhy the extra method for converting to brightness? Why not just this: def contrasting_text_color(background_hex_color) (background_hex_color.scan(/../).map {|color| color.hex}).sum > 382.5 ? '#000' : '#fff' end
- charliepark 16y agoCould certainly do it that way, if you don't need the brightness value. We have a color picker that sorts a hash of "available" hexadecimal colors by their brightness value, though, so we needed to have it available as an independent method.
- azymm 16y agoI also had to do something like this for my Python project and ended up with this: '#000' if int(my_color, 16) > 0xffffff/2 else '#fff' This approach isn't perfect, but it does the job.
- nitrogen 16y agoThere may be better ways of calculating brightness values for determining true perceptual contrast. Some starting points for the curious: http://en.wikipedia.org/wiki/Colorspace http://en.wikipedia.org/wiki/Colorspace http://en.wikipedia.org/wiki/YUV http://en.wikipedia.org/wiki/YUV http://en.wikipedia.org/wiki/HSL_and_HSV http://en.wikipedia.org/wiki/HSL_and_HSV http://en.wikipedia.org/wiki/YIQ http://en.wikipedia.org/wiki/YIQ The sample images at http://en.wikipedia.org/wiki/HSL_and_HSV#Disadvantages http://en.wikipedia.org/wiki/HSL_and_HSV#Disadvantages show the difference between various brightness calculations.
- jacobolus 16y agoYeah. I wrote the long one of those. What you should use for best results is something like CIELAB lightness. Basically the steps are: 1. Take "gamma-compressed" RGB and scale to the range [0, 1] (if it's an 8-bit integer representation, divide by 255), and convert to linear RGB: undo the sRGB nonlinearity or for the lazy, take each component to the 2.2 power. 2. Take a weighted sum of R, G, B components. The weights for an sRGB/HDTV image are .2126, .7152, and .0722 for R, G, and B respectively. This gives you the luminance, Y. 3. Apply some non-linearity to the luminance to get a decent correlate of human-perceived lightness. A gamma curve w/ 2.2 gamma (that is, raise your value of Y to the (1/2.2) power) actually is an okay function to use. If you want a better one, feel free to use the CIELAB definition: L = 116 Y^(1/3) - 16, where L ranges from 0 to 100. 4. Anything with L >= 50, use black, anything with L < 50, use white. (properly L*, but hacker news will think I'm using the asterisk to indicate emphasis if there is more than one of them) Since this is likely only being calculated for a few colors (even up to dozens or hundreds), there's really not enough overhead in doing this math to worry about the speed.
- nitrogen 16y agoI found the HSV/HSL article immensely useful on a semi-recent project, as Google seems to have forgotten about the original references I used when I first learned about those two colorspaces (i.e. students' and professors' personal web sites, found using the Altavista search engine).
- 16y ago
- thristian 16y agoI wanted to do something similar to figure out which of the 256 colours available in my terminal-emulator would be reasonably visible against a black background. I wrote a bash script to answer the question, at the heart of which was this function: get_luminance_from_color() { # Return the luminance of a color as a number 0-65535. local red=$1 local green=$2 local blue=$3 # Colour weights from Wikipedia. Note bash doesn't have floats. echo $(( (2126 * $red + 7152 * $green + 722 * $blue) / 10000 )) } It works like this: $ get_luminance_from_color 16384 32768 16384 28101 ...which is to say, then input is an RGB tuple where each field is 0-65535, and the output is a single integer between 0-65535 representing the luminance. If the luminance is > 32767, it's a light colour, otherwise it's a dark colour.
- statenjason 16y agoInteresting. Made me think to write a simple mixin for sass. @mixin fg-contrast($bg) { background: $bg; $textcolor: #ffffff; @if lightness($bg) > 50% { $textcolor: #000000; } color: $textcolor; } Could also be done by using the red(), green(), and blue() functions, but lightness was simpler.
- chriseppstein 16y agoBingo! Such logic is supposed to live in the stylesheets with the design.