In the web browser, the font color is set to black by default. Have you ever thought about why? It's not rocket science, just because of the background and the text has high contrast so you can tell apart the text and the background.
When the background is white, you use the black font and when it's black you choose the opposite. But what if the background is not black and white but other colors? (Suppose we only have the black and white font in this world 😝😝)
The text on these buttons looks harmonious, right? (I take them from the Bootstrap document)
If I reverse the font color:
You still can see the text on most of the buttons but the contrast becomes lower.
Here's another example. On the dark blue background, the white font is easier to read. However, the black font is a better choice on the water blue background.
As a software engineer, I always implement the UI based on the design, I barely think about how the designer chooses the font color until a question comes up in my mind. What if I want to display a text on the background that will change its color dynamically? Like, on Monday it's white but on Tuesday it changes to blue.
How do you choose the font color?
We can choose font color based on the background luminance. According to the contrast ratio formula given by W3C Recommendation: ```
contrast ratio = (L1 + 0.05) / (L2 + 0.05)
- L1 is the relative luminance of the lighter of the colors, and
- L2 is the relative luminance of the darker of the colors
- L<sub>black</sub> is
0
- L<sub>white</sub> is
1
I will use L
to represent the luminance of the background color. Now, we can say if <code>(L + 0.05) / (L<sub>black</sub> + 0.05) > (L<sub>white</sub> + 0.05) / (L + 0.05)</code> we can use black(#000000) as the font color. Otherwise, use white(#ffffff).
Let's simplify the formula:
<pre>
(L + 0.05) / (0.0 + 0.05) > (1.0 + 0.05) / (L + 0.05)
(L + 0.05)<sup>2</sup> > (1.05 * 0.05)
(L + 0.05) > √(1.05 * 0.05)
L > √(1.05 * 0.05) - 0.05
L > 0.179
</pre>
We only need to calculate the L
. The formula to calculate the relative luminance is given by W3C Recommendation.
// suppose background color in hexadecimal formart: #ff00ee
function textColorBasedOnBackground(backgroundColor) {
backgroundColor = backgroundColor.substring(1);
const r = parseInt(backgroundColor.substring(0,2), 16); // 0 ~ 255
const g = parseInt(backgroundColor.substring(2,4), 16);
const b = parseInt(backgroundColor.substring(4,6), 16);
const srgb = [r / 255, g / 255, b / 255];
const x = srgb.map((i) => {
if (i <= 0.04045) {
return i / 12.92;
} else {
return Math.pow((i + 0.055) / 1.055, 2.4);
}
});
const L = 0.2126 * x[0] + 0.7152 * x[1] + 0.0722 * x[2];
return L > 0.179 ? "#000" : "#fff";
}
</code></pre></div><h2>
<a name="example" href="#example">
</a>
Example
</h2>
<p>Here's an example. You can observe the font color while changing the background color.</p>
<p><iframe
height="600"
src="https://codepen.io/louis-7/embed/pomPXVe?height=600&default-tab=result&embed-version=2"
scrolling="no"
frameborder="no"
allowtransparency="true"
loading="lazy"
style="width: 100%;">
</iframe>
</p>
<p>References:<br>
<a href="https://www.w3.org/TR/WCAG21/">Web Content Accessibility Guidelines (WCAG) 2.1</a><br>
<a href="https://ux.stackexchange.com/questions/114952/determine-the-best-text-color-for-a-given-background-color#:~:text=In%20your%20case%20you%20simply,on%20the%20highest%20contrast%20ratio.&text='Pleasing%20to%20the%20eyes'%20is%20very%20subjective">Determine the best text color for a given background color</a><br>
<a href="https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color">How to decide font color in white or black depending on background color?</a></p>
Top comments (5)
Soon we'll be able to do this in CSS with
color-contrast
.You can add any number of colors and it will pick the one with better contrast automatically.
developer.mozilla.org/en-US/docs/W...
@fabiogiolito thanks for sharing this! This function is cool, it can compare colors other than black and white.
Omg that's incredible news! Hope implementations start cropping up soon.
Nice demo! Here's a version that I think is a bit more self-documenting and also rejects invalid inputs:
\p{AHex}
in a Unicode-aware regex matches any ASCII hex digit.@lionelrowe I was going to create a gist to provide a comprehensive function. Yours is awesome!