1

Is the following hypothesis true?

For any given color:

{ Hue, Saturation, Lightness_1 }

there exists:

Lightness_2

such that the contrast ratio between:

{ Hue, Saturation, Lightness_1 }

and

{ Hue, Saturation, Lightness_2 }

is at least 4.5.

Bonus question: How could I find such Lightness_2?

  • 1
    In the WCAG definition of ‘contrast ratio’ that you linked to, L1 and L2 are used as symbols for relative luminance which is usually indicated by Y instead (as in XYZ or xyY), which in turn is easily and often confused with luma Y’ (as in Y’UV or Y’CrCb). In HSL colors, however, the L stands for lightness! L = (max(R,G,B) + min(R,G,B)) / 2 – Crissov Jul 31 '15 at 12:19
  • @Crissov Thanks for pointing this out. I updated the question to avoid this confusion. – Misha Moroshko Jul 31 '15 at 12:23
  • Cross-post – unor Jul 31 '15 at 17:28
2

There is no simple formula that links L in HSL with WCAG contrast ratio or relative luminance Y (or what WCAG confusingly calls L). However, there is one for RGB which allows you to use some algebra to find colors that contrast at a certain level with another known color.

Find the Brightness (Relative Luminance) you Need

Contrast ratio, C, is:

C = (Y1 + 0.05) / (Y2 + 0.05)

Where Y1 and Y2 are the relative luminance, Y, of the two colors; Y1 is the lighter color, whether it’s foreground or background. You can get Y from RGB values with:

Y = 0.2126 * (R/255)^2.2 + 0.7151 * (G/255)^2.2 + 0.0721 * (B/255)^2.2

That’s not quite the formula used by WCAG, but it gets pretty close, and makes the algebra much easier. If you “pad” your 4.5 minimum a bit, you’ll be safe in meeting the standard. Let’s use C = 4.6.

So, if you’ve already selected the lighter color, then the answer to your second question (but using Y2, not Lightness_2) is:

Y2 = (Y1 + 0.05) / 4.6 – 0.05

Y2 = [ 0.2126 * (R1/255)^2.2 + 0.7151 * (G1/255)^2.2 + 0.0721 * (B1/255)^2.2 + 0.05 ] / 4.6 – 0.05

Y2 = ( 1.0794e-6 * R1^2.2 + 3.6306e-6 * G2^2.2 + 3.6606e-7 * B2^2.2 + 0.05 ) / 4.6 – 0.05

Where R1, G1, B1 are the RGBs of your known color. If your lighter color is a pale blue (192, 224, 255), then Y1 = 0.7237, and Y2 = 0.1182

Finding a Specific Color

There are many many colors that will equal Y2 (many possible combinations of RGB), and many many more that are equal to or less than Y2. To actually determine a color, set some constraints of the relative proportions of RGB, and continue with the algebra. Select constraints that will get you in the ballpark of the color you’re looking for. You can always fiddle with the RGB (or HSL) values afterward, and check if it still complies with the WCAG standard.

For example, let’s say you want a nice rich shade of brown. Browns have an R to G ratio of about 2:1, or R2 = 2*G2. To keep it rich, we’ll set B2 = 0. Let X = G2, so:

Y2 = 0.2126 * (R2/255)^2.2 + 0.7151 * (G2/255)^2.2 + 0.0721 * (B2/255)^2.2

Y2 = 0.2126 * (2*X/255)^2.2 + 0.7151 * (X/255)^2.2 + 0.0721 * (0/255)^2.2

Y2 = 4.9595e-6 * X^2.2 + 3.6306e-6 * X^2.2

Y2 = 8.5901e-6 * X^2.2

Y2 is 0.1182, so solving for X

X = (0.1182 / 8.5901e-6) ^ 1/2.2 = 76

So your RGB color is 152, 76, 0.

Adjusting your Color

That 152, 76, 0 has an L of (152 + 0)/2 = 76 (see Crissov’s comment). If you reduce L, you’re sure to get better contrast. However, if you leave L constant and vary H or S, you might get a contrast ratio less than 4.5, depending how far you deviate from the current hue and saturation. Different colors with the same Ls will not necessarily have the same Ys. Using the above formulas, pure blue (0, 0, 255) and pure yellow (255, 255, 0) have the same L, but very different Ys. In fact, they have a C of 8 with each other!

If you don’t want to constrain your colors to achieve an algebraic solution, then make a spreadsheet with the basic formulas for relative luminance and contrast ratio or use WebAIM's Color Contrast Checker, and experiment with the RGB’s until you’re satisfied.

I’ve another example of a similar calculation at “How much darker should yellow be get the same contrast as other colors?

Regarding the Hypothesis

Oh, to answer your first question, yes, the hypothesis is true. For any given color, you can either crank up or crank down L until it reaches white or black. White has Y = 1 and black has Y = 0, so solving the contrast formula for the other Y for each tells you that any color with Y > 0.1750 will have C > 4.5 against black, and any color with Y < 0.1833 will have C > 4.5 with white. Between 0.1750 and 0.1833 are (relatively few) colors that contrast at least 4.5 with both black and white (e.g., 207, 0, 207).

The same cannot be said for the WCAG AAA normal text standard of 7.0. For that, there is a range of Y from 0.10 to 0.30 which comprises colors (e.g., 207, 0, 207) that cannot be used no matter what the other color its .

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.