Color Suggestions
in Accessibility Developer Tools
Alice Boxhall / @sundress
Color
Color contrast
contrast ratio
(L1 + 0.05) / (L2 + 0.05), where
Color contrast
axs.color.calculateContrastRatio = function(fgColor, bgColor) {� var fgLuminance = axs.color.calculateLuminance(fgColor);� var bgLuminance = axs.color.calculateLuminance(bgColor);� var contrastRatio =
(Math.max(fgLuminance, bgLuminance) + 0.05) /� (Math.min(fgLuminance, bgLuminance) + 0.05);� return contrastRatio;�}
contrast ratio
(L1 + 0.05) / (L2 + 0.05), where
Color contrast
axs.color.calculateContrastRatio = function(fgColor, bgColor) {� var fgLuminance = axs.color.calculateLuminance(fgColor);� var bgLuminance = axs.color.calculateLuminance(bgColor);� var contrastRatio =
(Math.max(fgLuminance, bgLuminance) + 0.05) /� (Math.min(fgLuminance, bgLuminance) + 0.05);� return contrastRatio;�}
contrast ratio
(L1 + 0.05) / (L2 + 0.05), where
Luminance
relative luminance
the relative brightness of any point in a colorspace, normalized to 0 for darkest black and 1 for lightest white
Note 1: For the sRGB colorspace, the relative luminance of a color is defined as
L = 0.2126 * R + 0.7152 * G + 0.0722 * B where R, G and B are defined as:
and RsRGB, GsRGB, and BsRGB are defined as:
Color representation: RGB
Green
Blue
Red
rgb(255 , 0, 0)
rgb(0, 255, 0)
rgb(0, 0, 255)
Luminance
relative luminance
the relative brightness of any point in a colorspace, normalized to 0 for darkest black and 1 for lightest white
Note 1: For the sRGB colorspace, the relative luminance of a color is defined as
L = 0.2126 * R + 0.7152 * G + 0.0722 * B where R, G and B are defined as:
and RsRGB, GsRGB, and BsRGB are defined as:
Luminance
relative luminance
the relative brightness of any point in a colorspace, normalized to 0 for darkest black and 1 for lightest white
Note 1: For the sRGB colorspace, the relative luminance of a color is defined as
L = 0.2126 * R + 0.7152 * G + 0.0722 * B where R, G and B are defined as:
and RsRGB, GsRGB, and BsRGB are defined as:
Gamma compression
Luminance
axs.color.calculateLuminance = function(color) {� var rSRGB = color.red / 255;� var gSRGB = color.green / 255;� var bSRGB = color.blue / 255;� var r = rSRGB <= 0.03928 ? rSRGB / 12.92 : Math.pow(((rSRGB + 0.055)/1.055), 2.4);� var g = gSRGB <= 0.03928 ? gSRGB / 12.92 : Math.pow(((gSRGB + 0.055)/1.055), 2.4);� var b = bSRGB <= 0.03928 ? bSRGB / 12.92 : Math.pow(((bSRGB + 0.055)/1.055), 2.4);� return 0.2126 * r + 0.7152 * g + 0.0722 * b;�};
Color contrast
axs.color.calculateContrastRatio = function(fgColor, bgColor) {� var fgLuminance = axs.color.calculateLuminance(fgColor);� var bgLuminance = axs.color.calculateLuminance(bgColor);� var contrastRatio =
(Math.max(fgLuminance, bgLuminance) + 0.05) /� (Math.min(fgLuminance, bgLuminance) + 0.05);� return contrastRatio;�}
contrast ratio
(L1 + 0.05) / (L2 + 0.05), where
Those color suggestions...
Color representation: RGB
Green
Blue
Red
rgb(255 , 0, 0)
rgb(0, 255, 0)
rgb(0, 0, 255)
Color representation: RGB
Green
Blue
Red
rgb(255 , 0, 0)
rgb(0, 255, 0)
rgb(0, 0, 255)
rgb(0, 0, 0)
Black
luminance = 0
rgb(255, 255, 255)
White
luminance = 1
Color representation: HSV
I ask for help
"My best guess so far is to convert C2 to HSV, change S by 1 (greater or lesser depending on whether the foreground is lighter or darker than the background), convert back, check contrast ratio, repeat until contrast ratio >= 4.5."
I get the best response ever
"I'd say the algorithm is pretty sound, but think of the adjustment _vector_ in 3-space (i.e. if Saturation is the desirable increment, consider you may be at a saturation limit so try adding a saturation "vector" but be prepared for it to clip or project onto the manifold of your 3-space .... also, if you're maxing out the desired vector, you may have to subtract the opposing vector from the 2nd color).
Also, L*ab is a fairly low-cost 3-space with (coarse) perceptual uniformity (IPT would be a better choice ... but they you're down in the weeds & really, consider 8bit RGB triples, it's of negligible benefit to extend that far).
In short, any invertible space is OK for color transforms ... just choose the space to make your calculations simpler/flexible. You can get away with affine transforms most of the time if your space is well chosen for the task."
Uhhhh...
By Ruby Wang (Own work) [CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons
We Can Do It!
Desired luminance
C = (L1 + 0.05) / (L2 + 0.05)
↓
L = C(L2 + 0.05) - 0.05
Color representation: RGB
Green
Blue
Red
rgb(255 , 0, 0)
rgb(0, 255, 0)
rgb(0, 0, 255)
rgb(0, 0, 0)
Black
luminance = 0
rgb(255, 255, 255)
White
luminance = 1
Luminance...
L = 0.2126 * R + 0.7152 * G + 0.0722 * B
Luminance...
Luminance...
L = 0.2126 * R + 0.7152 * G + 0.0722 * B
(Formula taken from [sRGB] and [IEC-4WD]).
IEC-4WD
IEC/4WD 61966-2-1: Colour Measurement and Management in Multimedia Systems and Equipment - Part 2.1: Default Colour Space - sRGB. May 5, 1998.
sRGB
"A Standard Default Color Space for the Internet - sRGB," M. Stokes, M. Anderson, S. Chandrasekar, R. Motta, eds., Version 1.10, November 5, 1996. A copy of this paper is available at http://www.w3.org/Graphics/Color/sRGB.html.
By Ruby Wang (Own work) [CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons
Luminance...
L = 0.2126 * R + 0.7152 * G + 0.0722 * B
Luminance...
Luminance...
Luminance...
Luminance...
Luminance...
YCbCr
Color representations: a chart
RGB → YCbCr
RGB → YCbCr
RGB → YCbCr
axs.color.toYCbCr = function(color) {
var rSRGB = color.red / 255;
var gSRGB = color.green / 255;
var bSRGB = color.blue / 255;
�
var r = rSRGB <= 0.03928 ? rSRGB / 12.92 : Math.pow(((rSRGB + 0.055)/1.055), 2.4);
var g = gSRGB <= 0.03928 ? gSRGB / 12.92 : Math.pow(((gSRGB + 0.055)/1.055), 2.4);
var b = bSRGB <= 0.03928 ? bSRGB / 12.92 : Math.pow(((bSRGB + 0.055)/1.055), 2.4);
�
return new axs.color.YCbCr(axs.color.multiplyMatrixVector(axs.color.YCC_MATRIX,
[r, g, b]));
};
Using YCbCr to pick a new color
Background color
Foreground color
Using YCbCr to pick a new color
Background color
Foreground color
Better foreground color
Using YCbCr to pick a new color
Background color
Foreground color
Better foreground color
var translatedColor = [luma,
ycc.Cb,
ycc.Cr];
return axs.color.fromYCbCrArray(
translatedColor);
Using YCbCr to pick a new color
Background color
Foreground color
???
Using YCbCr to pick a new color
Background color
Foreground color
Better foreground color
Using YCbCr to pick a new color
Foreground color
Background color
Using YCbCr to pick a new color
Foreground color
Background color
Better background color
So now you know.
Thank you!
Alice Boxhall
@sundress