How We Created an Accessible, Scalable Color Palette
A case study of how we launched a color palette across all platforms at Modern Health
During the latter part of 2021, I reflected on the challenges we were facing at Modern Health. One recurring problem that stood out was our struggle to create new products with an unstructured color palette. This resulted in poor communication between designers and developers, an inconsistent product brand, and increasing accessibility problems.
The color palette we use today at Modern Health for all user-facing products follows these principles, as defined by our design system:
- Inclusivity: our palette provides easy ways to ensure our product uses accessible contrasts. Color groups and their steps have been chosen for UI familiarity and a clean look that reinforces the brand.
- Efficiency: our palette is diverse enough for our current and future product design, yet values are still predictable and constrained. This framework allows for color groups to evolve over time and enables the addition of future colors.
- Reusability: our palette is on-brand but versatile. There are very few one-offs that fall outside the palette. Our palette should be effective across any user-facing digital applications at Modern Health.
This article shares the process I followed to apply these principles to develop a more adaptable color palette that prioritizes accessibility and is built to scale into all of our future product design needs.
Overview
Problem to Solve
How can we maintain a color palette that is consistent with our growing product brand, communicated accurately between design and engineering, and be accessible across a broad spectrum of visual needs?
The design system vision: Clearly defined and easily understood documentation supporting a centralized architecture that empowers all product teams to launch products efficiently.
Web audit
I ran our member-facing site through cssstats.com and found — unsurprisingly — that we had a lot of single-use color declarations and many references to hardcoded hex values. Despite the relatively limited palette in the existing user experience, there was a lot of repetition without clear guidance on how color should be applied.
Colors organically appeared in designs and code over time and — in an attempt to organize them — were given human-readable names. Using these names was unscalable; designer-developer communication couldn’t happen consistently, nor was there any way to know a color’s value by name alone.
I also ran color contrast accessibility audits using the WAVE Chrome extension. This informed us of low-contrast content in most core areas of the user experience. A low-contrast experience excludes users. It’s an easily solvable problem but isn’t always apparent to those without visual impairments or who are tasked with rapidly releasing features without a color framework on which to rely.
The first palette in the design system
My first pass at creating a color framework happened weeks after I started at Modern Health. I created a Foundation library in Figma that gathered the most common colors, reduced them down to a limited set, and applied a simple lightness scale and basic naming convention.
This Foundation palette was created by bucketing colors into color groups and reorganizing them around their lightness values (the L in HSL). The hex values were then hand-tweaked to give them a uniform look and to nudge them toward more accessible contrast levels. These colors were based on the brand guidelines.
It was clear that the way we named colors wouldn’t be the right way our product teams could communicate colors.
Even though we were making baby steps, we would soon hit a wall with how this framework would scale to our needs. We still lacked clarity on how colors should be applied consistently and we still weren’t putting accessible design first.
Why this framework didn’t work
The HSL (Hue Saturation Lightness) color model was the backbone of this original color framework, but anchoring around lightness and hand-tweaking isn’t the best way to scale, nor are we making accessible colors easy enough to apply as designers. However, in researching color models and exploring the work of other great design systems, I found many resources pointing to more human-friendly color models. After comparing and contrasting the ways these models could apply to digital design, I found an approach that was practical and applicable to our problem.
HSLuv is a modification to HSL that uses the same idea of Hue Saturation Lightness but in the CIELUV color model, which presents color lightness in a way that mimics real human perception. The difference, illustrated below, is most apparent when colors are placed in a lightness scale in equal steps.
With a new color model and key issues to address, we also focused on envisioning the future of our product design. During this process, we experimented with color to add vibrancy and distinction to our features. Our goal was to pressure test this new color palette that could adapt to our evolving product vision while also complementing our existing designs.
Goals & Approach
Our goals with this project, as adapted from the problem statement:
We want a centralized palette, accessible color contrast, clear naming conventions, and the ability to progressively improve and scale our colors within this framework.
Goal #1: Centralizing the palette
We wanted colors in the Foundation to be available in a library for all product UI in Figma and mirrored exactly in the coded foundation library. I started with the current Foundation palette, plotted as swatches on a lightness scale so we could observe the values in relation to each other.
I identified and created base colors (highlighted below) in each group and applied HSLuv color conversion, with the help of a Figma plugin, to create evenly distributed steps and form a broader, more cohesive palette. Unfortunately, hot pink
didn’t make the cut.
When the colors are desaturated, rows of color lightness can be clearly seen in the HSLuv color model. Even though the lightness values are similar in the original set, their perceived lightness is varied. This means that we could standardize color contrast in clear steps and that these steps would be consistent, regardless of hue.
Goal #2: Making contrast accessibility easy
We wanted good color contrast to be easier to understand and apply, WCAG AAA compliant (7:1 contrast ratio) for most text, AA compliant for some actions and icons (4.5:1), and AA+ (3:1) for large text and non-necessary visual aids. Taking this approach would also open us up to new concepts such as theming (e.g. dark mode).
We can much more easily predict the color contrast ratio in this new model. Every row has the same normalized lightness, making contrast ratios the same, regardless of color pairings. We can combine colors of different lightness and different color groups and still guarantee consistent contrast ratios. This enabled easier ways to design contrast-compliant color themes.
Goal #3: Consistent naming conventions
We wanted color names to be human-readable, based on a consistent and predictable scale, and allow for adding new color steps and color groups. In normalizing these conventions, we wanted the communication between product partners to be frictionless.
We would use familiar names for color groups, removing ambiguity. At this point, we’ve entirely eliminated references like weepingWhaleBlue
. The numeric scale was also changed to be between 0 and 100, which made communicating the color’s appearance easy, even when only reading the name. For example, the color blue-05
is a very light blue while blue-55
, in the mid-range, would be more vibrant, neither dark nor light.
We also chose to make the steps of each color group consistent, but not necessarily equal steps of 10. Anchoring around this lightness scale gave us more ways to effectively combine colors in our products and made the lightest and darkest colors more useful overall.
Goal #4: A framework built for scale
As we learned more about our ideal product brand, colors were designed to change safely over time. We also made migrating legacy designs to a new color system easier in both Figma and in code.
In addition to migrating the old palette to the new one, we were also looking toward the future. Given a more easy-to-use, accessible palette, we could now think in terms of theming components and layouts, e.g. dark mode.
Providing this framework—guided by clear standards and a consistent naming convention—also made it much easier to make changes and incorporate new colors (more on that in The Results below).
Writing Guidelines for Responsible Color Design
Clear documentation is of utmost importance when managing a design system. In writing concise and easily understood color usage guidelines, I chose to focus on two things:
- WCAG guidelines for color contrast
- Common UI colors
WCAG color contrast
We design with a minimum WCAG AA accessible ratio (4.5:1 minimum ratio) for all text, but our guidelines (as well as our coded library components) make sure that most text is AAA compliant (7:1 ratio). A significant part of the Modern Health experience — like most of the web — is written language, so providing designers with easy mechanisms for serving high-contrast designs was necessary.
We serve a large community and the design system should be fundamentally inclusive. Here are the overview guidelines for color contrast:
Common UI colors
In addition to contrast guidelines, we also provide references and general usage guidelines for colors. This allows our design team to creatively make use of our entire palette while keeping the core UX consistent.
The Results
Since introducing the new palette in Figma, we’ve also migrated all of our web applications to use the codified equivalent in our design system. It’s been so exciting to see features fully referencing color variables like color.blue-55
instead of a myriad of hardcoded hex values.
All of these changes, vetted by our entire design team, have greatly improved our accessibility goals, ensured better consistency in our designs, and elevated the overall user experience. As a result, our developer experience has also been enhanced, enabling us to launch products more efficiently than ever before.
Here’s an application example from our design system Storybook documentation site:
import { Button } from '@modernhealth/vital-components';
import { colors } from '@modernhealth/vital-foundation';
const StyledVitaButton = styled(Button)({
backgroundColor: colors.red55,
borderColor: colors.red55,
color: colors.white,
':hover': {
backgroundColor: colors.red40,
},
});
Future-proof
When the time came to make changes, we were well-prepared. The whole premise of a design system is to centralize and single-source assets, so when we determined that we needed a new color group, it was incredibly easy to make the transition.
This is how green was introduced into our libraries.
Similarly, we found the need to update colors to better represent the tone of our products. Yellow, in particular, felt out of place with the rest of the palette. Again, it was a few simple adjustments and suddenly our entire yellow color palette was updated everywhere.
Next steps
We’re more confident than ever that our color palette reflects our modern product brand and supports our principles of inclusivity and usability. In the future, we hope to continue to push the boundaries of theming, color gradients, and more.
We are also exploring proper design tokens for foundational styles like color. Design tokens would make centralized code even easier to maintain as well as put more of the control in the hands of the design team.
Because of the thoughtfulness that has gone into this color framework, any future changes and additions will be more straightforward than ever before. This minor investment has paid off multiple times already and I look forward to all of the other frameworks for UI design that we can adopt in the design system.
Huge thanks to my partners on our design team who vetted these ideas with me, my manager who pushed my work to higher quality, to my engineering partners who made this dream a technical reality, and to our product teams who spread the good word and adopted this system with grace. And special thanks to all of the influences, researchers, and giants upon whose shoulders I sit.