Creating accessible color contrast

A while back, I wrote about how color blindness can affect the implied meaning in our usage of color. The use of stoplight colors for status is less meaningful if your eyes aren't helping you distinguish between red and green. We got around this problem through the use of meaningful shapes in addition to the colors.

A grid of the coffee status in 5 offices, using color and shape to create status icons that are accessible to users with color vision deficiencies.

These steps are important for ensuring our meaning exists when the color isn't a guarantee. But what about when we're using color in ways not necessarily tied to a specific meaning? It's not so much of a problem, right? A color blind user — or really anyone — doesn't actually need to decipher the exactly color value of a green button, or a blue link, right? Of course not… assuming they can actually see it.

A phone with a heavy glare from a sunny day. There is yellow text on a white background in diminishing sizes, reading "Can you read me?" and smaller "How about now?"
Color choices may look fine to your eyes in your work environment, but how will it look on a device on a sunny day?

To ensure text, controls, and other vital pieces of information are intelligible, we need to understand the contrast ratio between the foreground and background colors. If the ratio is too low, it becomes harder for people with even perfect eyesight to read.

From an aesthetic perspective, there is a tendency to think of high contrast as (on a good day) bold or (on a bad day) garish. But  if we don’t meet a minimum threshold, we can’t ensure users can read the text, or understand an object is interactive.

Examples of high / low contrast in greyscale and color

Think about our Stoplight colors used before. What if we wanted to use those colors for a set of text labels (ignoring for a moment the implications with color blindness)? What jumps out as a problem? Yep… that yellow (#FFD300, for reference) on a light background would be extremely difficult to read. But how do we know when the contrast is high enough to be read by most people? Do we just darken it until we can read it? Until a few people around your desk can read it? If people in a meeting can read it? Oh, this is getting hard.

The W3C is here to help. As part of the Web Accessibility Initiative, they've written some detailed, dense guidelines on everything related to a digital experience (including things you might not expect, like timing and motion). These are called the Web Content Accessibility Guidelines, or WCAG. There are varying grades of support, from a bare minimum (A), to an acceptable level of accessibility (AA), and topping out at the gold-standard accessible experience (AAA). In AA, "normal" text — like the body of this article — should have a contrast ratio of 4.5:1 between the font color and the background. For larger text — bigger headers and metrics — it's 3:1.

When a color isn't quite to the AA standard, we can do some work to get it closer. The first step is to ensure the color will only be used on a certain set of background colors. We need to constrain the situation to get control of the variables at play. If we used the Stoplight yellow on a black background, it would actually be compliant. But in our case we have a light background. But how light is it? Is it white? Or will we be using some table rows and containers with a light grey background? Is there an informational banner with a light blue background using this text color? We need to know where this will be used to ensure the contrast meets the bar in each case, and test against the darkest (or lightest) allowed color. For our example, though, we'll stick with a white background.

There are two properties we can adjust on a color picker to still use the same Hue (the core color value) but get our color closer to compliant. We can adjust the Saturation and the Brightness. There is a color notation (similar to RGB) called HSB (you'll see that in some tools) or HSV. This is Hue, Saturation, and Brightness / Value. There's a similar notation in CSS called HSL, but the values are different. You can read more about the difference between HSL and HSB. I'll focus on HSB / V because it's used in most design tools (you can convert these values to any notation after that).

A macOS color picker window showing HSB sliders
Using the macOS color sliders to edit the HSB vaues.

If we need higher contrast with white, it means we need to RAISE the Saturation and / or LOWER the Brightness. We won't touch the Hue, as it defines the core aspect of the color and not the the resultant contrast directly. This takes some finesse, but if the color has a high Saturation (the i.e., closer to 100%), we'll have to lower just the Brightness, and vice versa. Using color contrast tools like Stark or Colour Contrast Analyser can help when fiddling with the colors.

Working with the Stoplight colors, the green and red were close to 4.5:1, and will get a little less bright, but still look like green and red while achieving AA contrast. The yellow, however, was an invisible 1.4:1, and with adjustment ends up #8D7400, a sort of muddy brown. This is not at all like our previous yellow… but you could read it, right?

Two Colour Contrast Analyser windows, one showing the yellow value failing contrast, and the other showing the compliant, yet muddy, brown

Sometimes you can't adjust a color to improve the contrast without making a noticeable change. The yellow has to change so much it makes an aesthetic impact, one that begs the question "Why are we using this color?" Of course, our choice of yellow was extreme and absurd, but these sort of shifts happen all the time. Bazaarvoice's brand teal is bold and iconic, but has a contrast ratio against white of 3:1, which makes it okay for bigger words like headlines, but for regular text it does not meet the AA standard, which is why we don't use the color for links and buttons inside Bazaarvoice Console. Adjusting the color with the previous technique yields a color that was deemed just divergent enough, leading us to use a lighter version of BV Navy blue instead.

Comparison of Bazaarvoice's teal, a AA compliant adjusted color, and the blue we ended up using instead
(Portal was renamed Console since writing this)

Working with color can seem like an artistic exploration to some, an ephemeral task invoking muses and impulse. But to really work with color in an inclusive manner takes effort, dedication… and some math. It takes balancing the aesthetic tastes of those with a keen eye and the needs of the everyday person just trying to figure out what to tap next. Luckily, we have guidelines to help us get there.