Designing an accessible color scheme, again
By: Katie Riley
Tags: Colors, Product Design, Visual Design, Design, Accessibility

My breakthrough came when I read about the techniques used by the U.S. government web design system (USWDS), a source I often turn to for great examples of how to build accessibly.

They created a genius system to generate color families made up of 10 “grades” or shades of each color, numbered 5 through 90 (white is always grade 0 and black is grade 100).

This system guarantees accessibility with it’s “magic number” method: if you stack one grade over another, as long as there is…

50 points difference between two color grades ensures greater than 4.5:1 contrast

40 points difference between two color grades ensures greater than 3:1 contrast

The USWDS documentation lays out exactly how to build color families this way in a table that shows the precise relative luminance values each grade must fall between to make the magic number system work.

This is a great resource, but if you’re anything like me, you also might not have ever heard of relative luminance. Don’t worry, I got you.

While it may be oversimplifying, think of luminance values as how bright a color is from 0 to 1. White is the brightest color (1) and black is the darkest color (0). A larger number equals a lighter color.

Knowing this, the table above starts to make more sense; for example, Grade 5’s luminance can’t be any darker than 0.850 or any lighter than 0.930. Those luminance values are quite close to 1, so we can visualize that Grade 5 is very close to white, a very light color.

I also learned that the formula for calculating contrast ratios relies on these luminance values:

(L1 + 0.05) / (L2 + 0.05) L1: the relative luminance of the lighter of the colors

L2: the relative luminance of the darker of the colors

Because I wasn’t as familiar working with luminance values, and I had a hard time finding a tool to quickly translate a hex value into a luminance value, I decided I would instead translate the USWDS table into contrast ratios (as compared to white) using the formula above.

Grade 5’s luminance value can be no darker than 0.850 and no lighter than 0.930 What contrast ratio would a color with a luminance of 0.850 have against a white background? We know the formula for contrast ratio is lighter divided by darker We know that white has a luminance of 1 Applying these known values to the contrast ratio formula, you get: (1 + 0.05) / (0.850 + 0.05) = 1.17:1 Repeat for 0.930 (1 + 0.05) / (0.930 + 0.05) = 1.07:1 Solved: Grade 5 can be no lighter than 1.07:1 against a white background and no darker than 1.17:1

This helped me produce a resource in terms I could understand faster, and allowed me to use existing Figma plugins to more quickly calculate if my color was in range.

Following the table above could absolutely empower you to quickly create color families. In Figma, it’s as easy as firing up Contrast, drawing some rectangles, and adjusting HSL values until each color falls into the right range of contrast values (and you like the way it looks).

You can absolutely stop reading here, follow those ranges and create amazing and accessible color schemes.

I will only give you one more pro tip to do this in the browser version of Figma, or change your color space in desktop Figma, because there can be substantial differences in color between the two, and you’ll likely want to know what the colors will look like in the browser before committing to them.

But if you’d like to continue reading, I will show you how you can adjust the USWDS ranges to make them lighter or darker according to your preferences. It’s gonna get mathematical!

I personally found that the USWDS ranges, as written, produced color schemes that were a bit darker for Grades 60+ than I wanted; I wanted to get as much vibrancy as possible even from my darker shades.

Using the same formula for calculating contrast ratio, I set out to make some adjustments.

I started with Grade 60. In the USWDS table, Grade 60 had a contrast ratio range of 6:1–7:1. I wanted to lighten up the low end of the range to 5.5:1.

Since there’s 40 points difference between Grade 60 and Grade 100, I knew that Grade 60 would need to have at least 3:1 contrast against black (Grade 100).

What’s the maximum contrast allowed for Grade 60 to that can still achieve 3:1 vs. black? • Formula: (L1 + 0.05) / (L2 + 0.05) = contrast [lighter divided by darker]

• Black has a luminance of 0 x / 0.05 = 3

3 * 0.05 = 0.15

0.15 - 0.05 = 0.1 (maximum luminance value for Grade 60)

Convert that luminance value back into contrast against white: (1 + 0.05) / (0.1 + 0.05)

1.05 / 0.15 = 7:1 (maximum contrast value for Grade 60)

So I must leave the upper bound of the range the same: 7:1.

Grade 60 has a 50 point difference with Grade 10, so what’s the darkest Grade 10 can be to still achieve 4.5:1 versus Grade 60?

Assume the lightest Grade 60 can be is 5.5:1 What's the luminance of a color with a contrast of 5.5:1 against white? (manipulate the same formula) 1.05 / 5.5 = 0.191 - 0.05 = 0.141 Solve for Grade 10 luminance: x / 0.191 = 4.5

0.191 * 4.5 = 0.86 - 0.05 = 0.81 (maximum luminance value for Grade 10) Convert that luminance value back into contrast against white: 1.05 / 0.86 = 1.221:1 (maximum contrast value for Grade 10; can't be darker than this)

And finally, Grade 60 has a 40 point difference with Grade 20.

1.05 / 5.5 = 0.191

0.191 * 3 = 0.573

1.05 / 0.573 = 1.83:1 (maximum contrast value for Grade 20; can’t be darker than this)

Essentially, by using the formula for calculating contrast ratio and the concept of the magic number, you can continue to make any adjustments you’d like to the grade ranges. I adjusted most of them just slightly, ending up with this table of values:

* A firm limit; the system will break if you go beyond this value. Unmarked values could be exceeded slightly, if necessary for aesthetics or brand, without breaking the system.

I think these changes were noticeably helpful to make the darkest few grades more vibrant and less like “almost black” shades, which works better for our product.

USWDS ranges (above) versus my lightened ranges (below)