I am currently calculating the contrast of two foreground colors and a background color to programmatically decide if the foreground color should be white or black.
The formula for the contrast ratio is defined as
(L1 + 0.05) / (L2 + 0.05)
Where L1 is the relative luminance value of the lighter color and L2 is the relative luminance value of the darker color.
WCAG specifies that the optimal ratio for large text is 4.5:1 and for normal text 7:1.
I can't find an explanation as to why both values need to be incremented by 0.05...
Is it simply used to prevent dividing by 0 as the relative luminance for black is exactly 0?
Here are three reference sources:
- https://www.w3.org/TR/WCAG/#contrast-ratio (search for '0.05' using CTRL + F)
- https://www.accessibility-developer-guide.com/knowledge/colours-and-contrast/how-to-calculate/#the-formula
- https://planetcalc.com/7779/
Additionally, here is some code, have fun:
private static readonly Func<Color, double> CalcRelativeLuma = (c) =>
{
// Convert 8-Bit RGB to sRGB.
double R = c.R / 255.0;
double G = c.G / 255.0;
double B = c.B / 255.0;
// Calculate relative luminance for sRGB values.
R = R <= 0.03928 ? R / 12.92 : Math.Pow(((R + 0.055) / 1.055), 2.4);
G = G <= 0.03928 ? G / 12.92 : Math.Pow(((G + 0.055) / 1.055), 2.4);
B = B <= 0.03928 ? B / 12.92 : Math.Pow(((B + 0.055) / 1.055), 2.4);
return 0.2126 * R + 0.7152 * G + 0.0722 * B;
};
private Color GetHighContrastColor(Color background)
{
// Calculate relative luminance of background.
double l1 = CalcRelativeLuma(background) + 0.05;
// Set contrast colors and calculate relative
// luminance of them.
Color darkContrast = Color.FromArgb(36, 36, 36);
Color lightContrast = Color.FromArgb(239, 239, 239);
double l2 = CalcRelativeLuma(darkContrast) + 0.05;
double l3 = CalcRelativeLuma(lightContrast) + 0.05;
// Calculate contrast ratio for dark and light contrast
// in regards to the background color.
double ratio_dark = Math.Max(l1, l2) / Math.Min(l1, l2);
double ratio_light = Math.Max(l1, l3) / Math.Min(l1, l3);
// Choose which of the contrast colors to use.
double highContrastRation = Math.Max(ratio_dark, ratio_light);
Color contrast = Color.Transparent;
if (highContrastRation == ratio_dark) {
contrast = darkContrast;
}
else {
contrast = lightContrast;
}
return contrast;
}