Color palettes and accessibility features for data visualization
Colors can’t do it all. And data tables really aren’t so bad.
Last October, the Carbon team added Data Visualization (‘Carbon Charts’) to the growing family of open source libraries that deliver the IBM Design Language to software. Since then, we’ve published updates to the color palette, accessibility features, usage guidance, and major improvements to functionality and implementation.
This article aims to document our process, and also to share some of our underlying challenges. Open source systems can always use more bright minds, so we’d love to hear your thoughts!
A complex sub-system
Take one look at our website and you’ll see that Carbon’s data visualization library is like a mini-design system in itself. It has all the standard hierarchies of construction — elements, components, and patterns — each accompanied by usage guidance and code.
Elements, or primitives, are abstract and foundational. For example, color, typography, textures, shapes, iconography and in some cases motion. Although it may not seem as intuitive, we classify points, lines and (graph) areas as components because they are interactive and have reusable states. Finally, the chart type occupies the third level of this hierarchy. Since the charts are categorized by their use cases, chart types map to the way we think of patterns in the larger design system. This third level is where the system delivers the most value.
I will focus mainly on our work at the element and component level to maximize accessibility. Carbon Design System is compliant with the WCAG 2.1 web standard. The Success Criterion 1.4.11 Non-text Contrast (Level AA)—which describes that meaningful graphics has to be 3:1 contrast ratio against adjacent colors—poses a key challenge for data visualization. As we discussed in a previous article, some issues emerged with the first version of IBM’s brand color palette as it rolled out into products. Although we addressed them in a new release, the experience underscored the lesson that good design cannot rely solely on colors to convey meaning.
Drawing from IBM’s brand palette
Carbon’s core data visualization palette is a curated subset of IBM’s brand palette. Data visualization libraries rely on two types of color coding for data sets: sequential and categorical palettes. Sequential palettes — often light to dark shades of the same color — demonstrate ranges in a data sets (they’re often seen in heat and choropleth maps). Categorical palettes are used to assign non-numeric meaning to categories in visualizations.
A case for extended palette
Because IBM’s brand palette intentionally skews cool, we found ourselves running out of warm options for visualizations. A balance of warm and cool hues is essential to avoid creating false associations. For example, a single magenta data point in a sea of blues and greens can read as an error — or create the impression that the cooler data points are related. After some thought, we made one key addition to address this problem: an extended yellow and orange spectrum. The extension is only available for Carbon data visualizations.
Reduced background options
Strategic palette limitations are just as important as the additions for accessibility. Keeping background contrast ratios above the 3:1 accessibility requirement is a challenge in data visualization. So to enable maximum contrast, we restricted chart backgrounds to only the brightest (White) and darkest (Gray 100) of the theme backgrounds.
Accessibility and the sequential palettes
The sequential palettes are the easier problem to solve.
Carbon provides the same sequential palettes for both the light and dark themes, which means nearly half of the colors do not satisfy 3:1 contrast ratio against the background.
But maintaining a full range of light and dark is more effective for data reading, as it increases the differentiation between data points. As you can see below, a limited palette would render visualizations like heat maps meaningless for all users. Overemphasis on background contrast can thus reduce the accessibility inside the visualization. In turn, we rely on additional features such as axes and outlines to assist with the graphic’s read.
Here are some of the color-agnostic features we apply to visualizations using sequential palettes.
Accessible vertical and horizontal axes
Rectangular charts such as heat maps need to include 3:1 contrast-accessible x and y axes to help define the boundaries of the chart. We recommend including accessible axes in general to provide visual anchors for axes ticks.
Outlines
When using the sequential palette on maps, active regions should be outlined with a 3:1 contrast-accessible stroke against the background. Otherwise, regions with low contrast colors, especially islands, can easily get lost.
Caps on bars
Occasionally, a grouped bar chart might need the sequential palette. A border top of 1px stroke in an accessible shade can be added to assist the read.
Divider lines (situational)
A 1px stroke around a region (or around individual cell in a heat map) in the chart’s background color could be helpful. However, if the visualization is very dense, divider lines should be eliminated because they can eat up valuable space for displaying data.
Accessibility and the categorical palette
Since Carbon’s sequential palettes are either mono- or duo-chrome, we didn’t have to worry so much about hairy color combinations. Our categorical palette presented a much more challenging problem. It wasn’t enough to just define the palette — the sequence in which users apply the colors and the way they combine them to form a set also affects accessibility. Colors in a categorical palette need to be:
- Differentiated: they should have a sufficient visual contrast among themselves (optimized for all color deficiencies).
- Diverse: as a set they should avoid false associations or correlations due
to similarities in brightness or hue. - Sequenced: in order for the palette to be effective in visualizations with as few as 2, and as many as 14 categories, the colors need to be sequenced in such a way that differentiation and diversity is evenly distributed.
To shed some light on how we arrived at a solution, I will briefly recap two of the rejected attempts at solving this challenge. For the final outcome, skip straight to Attempt #3.
Attempt #1: the computational method
Several co-workers at IBM had previously introduced a method for picking accessible color sets computationally. First, they eliminated the semantic colors (colors that denote values like warning or danger), and then they sequenced the swatches by skipping between color steps (or shades) and families. The Carbon team used this method to define our first-generation categorical palette.
The result was promising at a glance, but we quickly noticed that the dark theme palette performed much better than the one for the light theme. Achieving 3:1 contrast against the background required relatively dark colors in the light theme and — to a user with typical sight — differentiating between hues becomes much harder as brightness decreases.
This method excels at maximizing contrast between neighboring colors within a set. But when applied to a complex, color-rich dashboard like IBM Digital Analytics and IBM Cognos Analytics, light theme users would be looking at a lot of dark colors in a dense user interface. Purple 90, Magenta 90, Teal 90 and Green 90, would be hard to differentiate even for those with typical vision.
The IBM brand palette, intentionally minimal and essential, consists of only 104 colors to begin with. With the elimination of the semantic colors — blues, reds, and cyans — we just had too little room to maneuver.
Attempt #2: Alternating between accessible and inaccessible colors
Since the dark theme palette of Attempt #1 seemed viable, we kept it and started looking for ways to improve on the light theme palette. First, we expanded it to include shades that did not contrast 3:1 against background, while using the same method to pick colors computationally.
The resulting palette improved the distinction between the colors, and brightened the whole look. However, this approach would require adding border and outlines in some visualizations. It also relies on neighboring colors sufficiently contrasting in situations where the colors might touch.
Unfortunately for Attempt #2, the legends in our charts allow users to filter and isolate data sets. If a data category relies on the neighboring colors in order to achieve sufficient contrast, it could fail as soon as users begin interacting with the legends.
Attempt #3: the solution
After a lot of wrestling and iteration we landed on a solution that required both flexibility (loosening the rules) and manual curation:
1. We reintroduced some of the semantic colors back into the mix.
2. We extended the brand palette’s yellows and oranges (previously reserved only for alerts).
3. We manually picked and sequenced the colors.
We bought back Red 50, a very bold color loaded with meaning. The trick is to sequence it to appear after Magenta 70. With the hot magenta warming up the stage, Red 50’s appearance is less alarming. Though now Red 60 doesn’t read as error so much either! To solve this, we used a much thinner stroke and experimented with dotted vs solid line to create differentiation for chart annotations. These are some early explorations, but the general consensus is to not rely on color.
Presenting the Carbon data visualization categorical palette:
Evaluating the categorial palette
With these adjustments, the categorical palette is fully 3:1 contrast-accessible against background, and has an average of >2:1 contrast between neighboring colors. Since this falls short of the strict requirement of non-text contrast, we have built up a repository of color-agnostic features to assist with data read, which I will get into shortly.
A shortcoming of “contrast ratio” is that it only measures differentiation between two colors. To evaluate the effectiveness of a categorical palette, we need an index that measures the differentiation of all colors in the palette as a group, in all combinations and permutations.
We used Viz Palette made by Susie Lu and Elijah Meeks, to evaluate our results. Viz Palette generated color reports visualizing the just-noticeable difference (JND) between colors. A JND is defined as “the amount something must be changed for a difference to be noticeable.” Colors that are difficult to tell apart are linked with increasingly thick arcs.
Additional accessibility cues for the categorical palette
Divider lines
The divider line is actually more important in charts using the categorical palette, because here colors are used to differentiate between categories.
Although we’ve ensured that all the colors are 3:1 accessible against the background, it’s not possible to keep them 3:1 accessible against each other at the same time. So we’ll add a contrast divider in the theme background color to separate any touching colors.
Tooltips
Hover tooltips are a must-have to communicate more detailed information without over crowding the visualization. Carbon data visualization has two types of tooltips: single data point tooltip, and comparative tooltip for hover on multiple data points.
Single tooltips can be surprisingly complex, displaying up to 4 dimensions of data (name of category, values of both axis, and size dimension on some charts).
Comparative tooltips display multiple data points in one tooltip and may also provide a sum when relevant. If the cursor rests at any point between lines on line chart, or above a stacked bar, a tooltip ruler will appear and all y-axis outputs will be displayed for that particular x-axis time stamp.
Textures and shapes
Texture is a well-established alternative to color coding areas, though it also pose a scalability challenge. When textures are used on bar charts, the bars need to be outlined in a 1px stroke and double the width to ensure the patterns are recognizable.
Shapes can also serve as an alternative or enhancement to color coded data points. The main considerations when designing these are ease of differentiation and consistency of use. Just like semantic colors, certain shapes can have semantic meaning too (e.g. triangles for warning or caution). For this reason, it’s important for teams to align on their use, especially in status alerts.
Another drawbacks is users would have to trace the line to read categories. To avoid this, use shapes in combination with colors.
Keyboard navigation
Carbon is still working on implementing keyboard navigation for charts. Future functionality will allow users who are tabbing through a page to focus on individual data points in a given chart by pressing ‘Enter’, and then ‘Tab’ again to exit the chart. This will allow keyboard users to access the hover tooltips inside the graph frame.
Data table
Although they sometimes require a little work to understand, data tables are the most accessible way to present data. They also happen to be the most unbiased, in that no design decisions could potentially mislead users (e.g. a poor color decision or not starting the y-axis at 0). “View as data table” should always be an option in the visualization’s overflow menu.
Closing note
Thank you for sticking with me till the end!
The Carbon data visualization library is still very much a work in progress. Here are some areas that are currently in the works or on the road map for future exploration:
- Zoom and pan
- Annotations
- Skeleton, empty, and error states
- Axes and labels
- Entrance motion and interaction animations
- Dashboards
Meet the team
I cannot say enough good things about the stellar talents I’ve worked with during this project. Data visualization is a world we all love and it will be an ongoing journey.
This has been a collaboration between many disciplines and teams — including the Accessibility team, Cognos Analytics, SPSS, Security, and Cloud.
Design: Shixie, Cameron Calder, Sadek Bazaraa, Jeannie Servaas
Development: Eliad Moosavi, Dean Williams, Natasha Decoste, Zvonimir Fras, TJ Egan
Accessibility: Mike Gower
Key sponsor users: Anne Stevens, Tricia Garrett, Diana Tran, Derek Bressler, David Levinson, Anna Hazard
Agency partner: Accurat, Guidea
Co-written with Jeannie Servaas, Anne Stevens and Mike Gower.