Skip to content

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
Color_mapping_A Color_mapping_B
× = 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
Concept_palette Concept_palette_2

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
Screen_Shot_2019-11-07_at_9.40.16_AM Screen_Shot_2019-11-07_at_9.41.00_AM Screen_Shot_2019-11-07_at_9.41.14_AM
Screen_Shot_2019-11-07_at_9.40.45_AM Screen_Shot_2019-11-07_at_9.41.06_AM Screen_Shot_2019-11-07_at_9.41.19_AM
Screen_Shot_2019-11-07_at_9.40.49_AM
Screen_Shot_2019-11-07_at_9.40.56_AM
Roughly 8% of men and 0.5% of women are affected* Rare, ~0.008%* Very rare, ~0.001%*

*Source

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
Linear_transition Sequential_example_1
Hue_transition Sequential_example_2
Sequential_example_3

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
Categorical Category_example_1
Categoory_example_2

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
Diverging Diverging_1
Diverging_2
Diverging_3

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
Bar_chart Area_chart

Resources

/cc @gitlab-com/gitlab-ux @gtsiolis @ealcantara @sarahghp

Edited by Jeremy Elder