Data visualization color palette
TLDR;
This is a long issue about created a new palette specifically for data visualization. It may also be the longest issue you’ve read in some time, sorry!
Proposal
Explore adding a new color palette, specifically for data visualization, that is separate from the existing UI and theme palettes.
Purpose
It would be advantageous to have a new palette, comprised of hues that don’t have associated meaning or function, like those in the UI and theme palettes. For example, our UI red is associated with critical states, destructive actions, errors, fails, removals, or declines.
Exploration
I’m considering a palette with 5 hues that each have 11 steps from light to dark (current palettes also have 11 steps). Inspiration for the process comes from IBM’s Inclusive Color Sequences for Data Viz in 6 Steps post. The outcome indeed does feel similar to where IBM netted out with their palette, as we have many of the same challenges. The primary challenge for us being a palette that already has meaning associated with each hue.
Because I can’t be reductive by selecting impartial hues from a larger palette, my approach is to be additive—finding gaps in our current color sequence, and then refining those new hues for accessibility. Brand colors were included in the sequence, since they are also used in illustrations within the product.
Note: UI Purple is being addressed separately, but assumed for this exploration. This also includes other accessibility considerations for existing palettes that are not currently in Pajamas (like adjusting the orange for contrast). When issues have been created for that, they will be linked here.
Current color sequence | Color spectrum |
---|---|
× = gap | × = gap |
As you can see, a few gaps exist that would make room for a new palette. Arguably, the colors chosen in the palette below will be in the same family as existing UI colors, but given our current distribution across the palette, and the considerations for contrast and colorblindness, the margin is narrower than it looks. The bottomline is that I’m after nuanced differences, more than polarizing ones.
In general, purples have been avoided because of existing brand colors and themes, and they don’t differentiate themselves that well when considering colorblindness (several hues take on a purple cast when viewed with certain types of colorblindness). A larger range of yellow and green has also been avoided because of how muddy or muted they may appear when darkened enough to reach desired contrast levels.
Palette
Requirements:
- Explore gaps in the current color sequence, based on existing 500 values, where current hues do not exist
- Use hues that are not used strictly associated with meaning in the product today
- Simplify referencing values by knowing that anything ≥500 will meet or exceed a 3:1 contrast ratio on
#ffffff
, and anything ≤500 will meet or exceed a 3:1 contrast ratio on#1f1f1f
—effectively creating light UI and dark UI theme options from one new palette
Palette | Palette with light/dark UI |
---|---|
Surfaces
- In a light UI, all data visualization should be on a
#ffffff
surface - In a dark UI, all data visualization should be on a
#1f1f1f
surface
Accessibility
Contrast
Per WCAG 2.1 Success Criterion 1.4.11: Non-text Contrast, UI components and graphical objects must have a contrast ratio of at least 3:1 against adjacent colors. You’ll notice that if these colors were directly next to each other, many combinations wouldn’t have enough contrast. We’ll cover visual separators below. This exploration does not cover high-contrast mode offered in most operating systems.
Colorblindness
Here are the results for how the palette is perceived under different conditions. The order of the hues has been changed so that hues are grouped by perceived similarities.
Red-Green confusion | Yellow-Blue confusion | Limited or no color |
---|---|---|
Roughly 8% of men and 0.5% of women are affected* | Rare, ~0.008%* | Very rare, ~0.001%* |
I’ve primarily focused on the results of Deut and Prot, although it should be noted that Trit does reflect enough perceived difference in most instances. Again, I’m after perceived differences, many of which are minor. Grayscale is a consideration if data were to be printed, in which case I’d explore further adjustments in a print style sheet, but that’s out of scope at the moment.
Application
There are many ways data can be displayed. For our needs, I focused on three different data categories, and the way color supports each type.
Sequential
Sequential data uses color lightness to indicate a range from high/dark to low/light in a light UI, and high/light to low/dark in a dark UI. Color transitions can be one hue (linear) or have a hue transition.
Both light and dark sets have 6 color steps. On white, the color steps range from 500–950, and on #1f1f1f
the color steps range from 50–500.
Potential applications: stacked bar charts, heat maps, choropleth maps, funnels, cycle diagrams, clusters, pyramids, etc.
Linear and hue transition | Examples |
---|---|
Categorical
Categorical data (also known as qualitative or thematic) uses hue to differentiate qualitative data, and lightness to differentiate quantitive data.
With 5 hues in the palette we can alternate both the hue and lightness to create sequences with color and contrast differences. There are many patterns that can be explored (and have been by the IBM team within the linked article), and I’ve initially used a chevron-skipping pattern.
Potential applications: bar charts, pie charts, line graphs, stacked area charts, etc.
Mixed hue | Examples |
---|---|
Divergent
Divergent data moves in opposite directions from a central point. Color is used to indicate distance from the center with darker/lighter values on each end, depending on the surface.
The steps required to make a useful progression involve using lighter/darker values that would not meet 3:1 contrast on the surface, in this exploration I added a border around non-passing values that uses the 500 value from the relative hue.
The pattern for selecting values skips every other step. For data with a smaller range, the pattern could be a subset, skipping every other step from the larger sequence.
Potential applications: butterfly charts, choropleth maps, sparklines, etc.
Diverging | Examples |
---|---|
Visual separators
As mentioned before, colors meet or exceed a 3:1 contrast ratio against either a light or dark surface, but not necessarily each other. There are a few solutions, but the easiest is “whitespace” between each element. In a light UI, this means at least a 1px white gap between elements. In a dark UI it would be #1f1f1f
. Whether this is an actual gap, or border, the effect is the same. Other solutions can be explored ad hoc.
Pattern fills
Pattern fills have not been explored as part of this effort, with the intent to really focus on color. They have been explored in gitlab#28116 (comment 215739113), and the general conclusion is that they can create accessibility issues of their own, namely cognitive.
Highcharts concludes:
Keep in mind that pattern fills and dash styles could make your charts visually confusing and less accessible to some users, and that not all charts will be improved by adding these features. Subtle patterns are often preferred.
And in a related discussion on creating pattern fills in SVG, Charles Hall comments:
Yes, patterns are an option to mark differentiation and support the ‘color-only’ criteria. However, you have to tread very cautiously. Certain patterns can trigger discomfort for various cognitive, neurological and psychological conditions and states. For example, diagonal lines can trigger vestibular disorders when scrolling the page, and make reading more difficult for those with dyslexia.
Naming
The current naming patterns for swatches is:
-
$color-value
for UI colors and neutrals -
$t-color-value
for theme colors
For this new palette I propose $dv-color-value
, where dv
is shorthand for “data visualization.” In common speech the hues could be referenced as “data blue,” or “data yellow,” for example.
Color space
A quick note on color space… Originally I was wanting to explore P3, but have stuck with sRGB, which is a smaller gamut, but also a better common denominator. Interestingly enough, there is a color-gamut
media query candidate recommendation for color space, and it would be interesting to test this in a future iteration. With P3 we could explore more vibrant hues, potentially leading to better contrast, but many design apps still do not support it. I currently assign sRGB to all documents I work on in Sketch and Figma.
Examples
Actual examples that leverage the proposed palette (will have more added as they are created).
Bar chart | Area chart | … |
---|---|---|
… |
Resources
- https://medium.com/design-ibm/inclusive-color-sequences-for-data-viz-in-6-steps-712869b910c2
- https://design.lyft.com/re-approaching-color-9e604ba22c88
- https://www.colorbox.io/
- https://designsystem.digital.gov/design-tokens/color/overview/
- https://www.khanacademy.org/partner-content/pixar/color#color-space
- https://michelf.ca/projects/sim-daltonism/