I'm currently booking for my next available slot in August 2022. Get in touch.
The easiest way to build a WCAG 2.0 AA compliant color system
Mariano Miguel · 4 weeks ago
Anyone who has tried putting together a design system knows that creating a cohesive color palette that looks great but still promotes accessible color pairings, supports multiple themes, and endures over time is a nightmare.
There are many ways to it, but I'm going to show you a simple method that will guarantee you'll pass WCAG's AA standards color-wise pretty much every time.
The whole premise of this article is to provide you with a method to pass accessibility guidelines. This will effectively limit your choices and make the process more complex. You may also have to sacrifice some of the trendy low-contrast pairings to make your palette accessible. This is still a small price to pay for enabling a wider range of users to use your product.
Here's what you'll need to pass AA:
Regarding the rule about element boundaries, you can skip it if:
I first found out about this method when I came across the U.S. Web Design System (USWDS). They built a color-grade system that goes from 5 to 90 based on relative luminance, where each grade conforms to a specific range of values:
Grade | Minimum luminance | Maximum luminance |
---|---|---|
0 | 1.000 | 1.000 |
5 | 0.850 | 0.930 |
10 | 0.750 | 0.820 |
20 | 0.500 | 0.650 |
30 | 0.350 | 0.450 |
40 | 0.250 | 0.300 |
50 | 0.175 | 0.183 |
60 | 0.100 | 0.125 |
70 | 0.050 | 0.070 |
80 | 0.020 | 0.040 |
90 | 0.005 | 0.015 |
100 | 0.000 | 0.000 |
The difference in grade between any two colors is called the "magic number" (e.g: the magic number between red-90
and red-30
is 50
). While this may seem complex at first sight, the beauty of the system lies in its simplicity:
The beauty of this method is that you don't have to worry about manually checking contrast ratios when pairing between different colors. As long as your target magic number is good, an accessible pairing is guaranteed no matter which two colors you pick.
Katie Riley from Envoy Design wrote a blog post on this exact method and came up with an amazing solution to translate the original table to work with color contrast ratios instead of abstract luminance values. Here's what that looks like:
Grade | Minimum contrast vs white | Maximum contrast vs white |
---|---|---|
0 | 1 | 1 |
5 | 1.07 | 1.17 |
10 | 1.21 | 1.31 |
20 | 1.5 | 1.91 |
30 | 2.1 | 2.63 |
40 | 3 | 3.5 |
50 | 4.51 | 4.67 |
60 | 6 | 7 |
70 | 8.75 | 10.5 |
80 | 11.67 | 15 |
90 | 16.15 | 19.1 |
100 | 21 | 21 |
You could definitely grab the values from the table, pick a starting point, and then modify the color's HSL values to fit the contrast scale. However, I've automated the entire process into a little app that you can use to generate accessible shades for every color in your system: the accessible color scale generator.
All you need to do is pick a starting color, and the system will automatically create the rest of the colors for you. The tool will also provide you with alternatives for each grade, going from less to more saturated colors.
The tool will also build a dark-mode scale for you. We keep variable names consistent with the light-mode scale, so you can easily switch between the two.
Once you're ready, you can copy your scale as a simple text list, JSON, or CSS variables. Repeat the process for your brand, secondary, and interface colors, and you got yourself an accessible color system!
Get my best advice on front-end development & design systems straight into your inbox.