This is a transcript of a talk I gave at nz.js(c0n); 2017.

Talk title slide with words “Around the world in 80 shades”

Kia ora, I’m Nat. I’m Head of Design for Figure.NZ. We’re a charity, and our mission is to help New Zealand become a data-literate democracy where everyone can use numbers in their thinking.

So, unsurprisingly, I think data visualisation is kind of important. Data viz is all about communicating stories held in numbers and helping people understand the questions to ask.

Table of data showing areas of NZ, census years, and median ages.

Can you tell, at a glance, what meaning is in this data? Are there any trends you should pay attention to? Any outliers or spikes or troughs?

Chart of median age of people in NZ by region as per 2013 census, showing younger age in Auckland and older in Marlborough.

Converting it to visual form helps us to immediately see what’s going on. It’s way more user-friendly than the tabular data. The same applies for maps.

Chloropleth map of median age in Wellington City as at 2013 census.

In map form, we can quickly see how the data is distributed.

Dataviz is awesome. It makes people happy. It helps to communicate the meaning held in data.

Lots of happy faces with some crossed out.

But dataviz that doesn’t include everyone is not so awesome

There’s heaps of stuff that might mean you can’t read a data visualisation, but there are some that we cause by how we design them.

Yeah, I’m talking about accessibility.

Slide with text ‘Accessibility is important’.

We put dataviz into our apps and sites because we want to make communicating information clearer, so I’m gonna go ahead and say we should actually try and deliver on that for everyone.

Excluding people from participating because of the way we choose to communicate information is not only unfair, it’s just plain bad business. We’re a service industry, so we need to serve and empower our users.

Slide with text “The insight should be communicated to anyone, regardless of ability”

The key thing we’re striving for when we’re making accessible visualisation is that the insight should be communicated to anyone, regardless of ability.

Data viz creators mess this up in loads of ways; no alt text, data not being keyboard navigable, or there being no alternate way to see the data. More complex visualisation can also be much harder for less educated people or those with cognitive impairment, even though we enjoy making it more and find it more interesting.

Most of us suck at all of these, but we’ve only got 30 minutes so let’s talk about colour-blindness.

Ishihara plate test slide for red-green color blindness with number ‘74’.

You probably think about this when I talk about colourblindness.

It’s part of the Ishihara plate test — you probably did this as a kid. What it’s measuring is colour vision deficiency. Despite the name, most colourblindness isn’t actually inability to see all colour. The test checks to see if you have decreased ability to perceive differences between colours.

Colourblindness is almost always. inherited, and it’s linked to the X chromosome. This means it’s more common in people who have XY chromosomes than people who are XX.

There’s also a whole bunch of forms — not just the red-green you might’ve heard of.

Chart of wavelengths of blue, green, and red light sensed by cones in eye.

Eyes work using sensors called rods and cones. The rods sense movement and brightness. The cones in our eyes sense colour — they respond to short, medium, and long wavelength light.

Table showing the different types of color blindness. 2% of European XY carriers are impacted by red cone issues, 6% by green cone issues, and less than 1% by blue cone issues.

There are 8 different types of colour-blindness.

Anomalous Trichromats have reduced sensitivity because the reception of one of these pigments is misaligned. Most colourblind people will be anomalous trichromats. This means they don’t have complete loss of ability, but it is significantly reduced.

If the cone type doesn’t work at all, you get a form of colour blindness call dichromacy.

There’s also partial or full monochromacy, which occurs when 2 of the cone types are either partially or fully non-functional, and rod monochromacy, when all 3 don’t function.

So how much of a big deal is this? The amount of people impacted depends on ethnicity and gametes. It’s most common in Europeans with XY chromosomes, including Pakeha, with somewhere between 6–9% of people affected. People of asian descent clock in at 5–7%, and Māori, Pacific, African, and South American XY carriers are 1–3%. XX carriers are less than 1% everywhere.

This makes it a rare bird in accessibility terms. It disproportionately impacts people who form part of the tech community. This almost certainly impacts members of your team. If you can’t motivate people to solve wider accessibility issues, at least you should be able to motivate them to start with this!

So what’s the problem with this and dataviz? Turns out that in dataviz, we rely on colour a lot to communicate meaning.

Let me show you a chart from the old Figure.NZ website. This is in all the forms of colourblindness. This was before we added a requirement for charts to be colour blind accessible.

Chart from Figure.NZ’s old site in all forms of color blindness. It’s not readable.

It’s…not great. Here’s how it looked for deuteranopes — that’s the 5% one.

Chart as seen by deuteranopes. 2 colors seem identical.

And partial monochromacy, which may seem less important when you look at the stats — it’s less than .1 of a % of people, but it is similar to how it appears for older adults with low contrast vision.

Chart as seen with partial monochomacy. 2 colors appear identical.

And yeah, that’s already a problem, and it’s going to become a bigger one.

Chart showing ratio of over 65s to 15-64 year olds in NZ, forecast to 2025. The ratio steadily increases to 30% by 2025.

So, what that all means is if we get this wrong, quite a lot of people aren’t going to be able to read the wonderful things we’re taking the time to create. Let’s do it right, then.

There’s 2 basic principles at play here:

1. Choose better colours.
2. Reduce your reliance on colour as the sole method of communication

Slide with text “1. Choose better colours.
2. Reduce your reliance on colour as the sole method of communication”

Let’s talk colour. There’s obviously more to colour than accessibility. We want visually appealing colours that communicate information in an ambiguous and unbiased way. Well, I want unbiased, if you want biased, that’s your call I guess. We also want them to be able to be distinguished.

Variation of hue and brightness as quadrants. Increased hue and brightness makes all people happy, including those with color blindness.

We want as much perceptual contrast between colours as possible, regardless of vision type. Perceptual contrast comes from difference in hue and in brightness or luminosity. The basic idea is that when your vision messes with hue, the variation in luminosity means you can still see what’s going on.

So, most people’s instinct is to start with colours that they think are visually distinctive. The classic example is the rainbow palette.

Rainbow spectrum shown in 4 different types of color blindness. The yellow and aqua colours are hard to distinguish.

But when you see how it appears for colourblind folks, it’s not so great. So we need to take a bit more care. We could mess about in Photoshop for hours trying out different combos, but no-one has time for that. Luckily the science of colourspaces is here to help. Once you understand a bit about them, you can use your math and magical JavaScript powers to help you out, and your designer friends (like me) will love you.

You do need to know a little bit about colourspaces, though, so let’s talk nerdy. A colourspace is a mathematical representation of colours. Not all colourspaces perfectly match what we can see.

Cube representation of RGB space

Most of us work using either hex codes or RGB values. They’re representations of the same RGB colourspace.

This is a cartesian coordinate based system (basically, you get 3 values that tell you which direction to go in along 3 axes to find the colour.)

But RGB doesn’t map to how we think about colour perception, and this makes it hard to use it to mathematically calculate good contrast palettes.

R: 94, G: 117, B:240

Like, it really doesn’t. Take a guess and see if you can figure out what the RGB for a colour 10% lighter than this.

R: 141, G: 157, B: 244

Yeah. And if I want to pick a colour either side of that that are visually and perceptively distinct?

🤷🏻‍♀️ shrug emoji

RGB blows for this. So what else can we use? Browsers also support another colourspace.

Hue, Saturation, Lightness.

HSL, which is short for Hue, Saturation, Lightness/luminosity.

Cylinder of HSL space showing saturation as radius, lightness from bottom to top, and hue as circumference.

HSL is a cylindrical coordinate system. You also get 3 values

Saturation runs 0–100 from grey to fully saturation.
Lightness runs 0–100 from black to white.

Circle of hue allocation in HSL space showing red at 0/360, green at 120, and blue at 240.

And hue is allocated along a spectrum from 0–360.

The Red primary is 0 (and also 360) because we’re going around in a circle.
The green primary is 120 degrees.
The blue primary is 240 degrees.

H 230, S 83, L 65

Let’s compare this to RGB.

So, here’s our value. And if we want one 10% lighter?

H 230, S 83, L75

You just adjust the lightness value.

Seems great, right? A predictable colourspace where we can apply simple math and get a result we expect?

Except for one thing. HSL doesn’t take into account perceptual brightness of hue.

Rainbow evenly space HSL values shown in monochrome as perceptually different.

These colours all have 100% saturation and 50% lightness — The only thing that varies is the hue; they are a perfect 60 degrees apart in hue separation. You’d think this means they look the same in monochrome.

But when you look at them in monochrome, not so much. They’re not perceptually equal.
This means using math to make colourblind friendly palettes doesn’t work so well.

Poop emoji on rainbow.

So where does that leave us?

Browsers don’t support any other colour spaces.

Words: CIEL*A*B*

Some folks at the CIE, which has a long French name I’ll say wrong but translates to International Commission on Illumination decided to standardise colourspaces.

They came up with the CIE L*a*b* colourspace. It includes all the colours we can perceive, and it’s not linked to a specific type of device (so it’s useful for other stuff like converting from RGB to CMYK)

Plot of axis of CIEL*A*B* space with hue circle, A axis, B axis, and L axis.

Quick primer: it’s also a cartesian plane system like RGB is, but it’s based on something called opponent colours theory. That basically says that a colour cannot be both green and red at the same time, or yellow and blue at the same time, so we can use a single value for each of these colour pairs. These run on an a and b axis, and there’s a vertical axis for luminance.

CIEL*A*B* rendered in 3D. This is almost impossible to describe.

This is a weird looking space. It’s not mapped nicely to a cone or sphere or cube, and it’s hard to imagine because it’s different at all 101 available levels of luminosity.

I bet you never thought colour was this complicated.

Rainbow spectrum in CIEL*A*B* shown in monochrome as identical.

BUT, the L*A*B* space solves our perceptual brightness problem. These colours all have the same lightness and same saturation (or chroma), but this time, when we convert them into greyscale, they’re identical.

The colours on the slide obviously aren’t a good colour scale to use for viz because we want to have variation in lightness!


LAB is awesome. Computers can use it to calculate colour palettes no problem, but it’s hard to use at a human level because it’s another cartesian coordinate based system. The UX is bad.

Meet L*C*Hº. Don’t worry, this is the last space. LCH is the more friendly cousin of LAB.

Hue circle showing math used to calculate the LCH values from LAB.

LCH takes the LAB space and turns it into a cylinder which keeps the perceptual uniformity. This means it’s like HSL in that we have hue represented by degrees, chroma as the radius from the grey centre, and lightness on the same vertical axis. The coordinates themselves are transformed with some basic trig. But unlike HSL, we don’t have that annoying uneven lightness problem.

This finally gives us a colourspace with a nice UX that we can use to obtain spectrums.


Crying emoji.

There’s no direct browser support. You can’t just plug LAB or LCH colours into your code.


Enter my good friend: Chroma.js

Chroma.js is going to become your buddy for working with dataviz.

An excellent dev took all of the complexity and packaged it up into one (tiny, 12kb) library. It does a lot of colour analysis and conversion, but what we really care about for this is that it can do interpolations in the LAB and LCH colourspaces and give you RGB or hex values at the end of it.

There’s even a plugin for D3, so you can use it directly when you’re making your data viz. By the way, if you’re not using D3 already, you should just accept our Lord and Saviour into your life. Don’t be tempted to roll your own. It can be a bit scary to start with, but long-term, it’s worth it.

chroma.scale([‘yellow’, ‘navy’]) .mode(‘lch’) .colors(5); with a spectrum from yellow to blue, and samples.

You can interpolate colour scales between two hex codes or named colour values. You can then specify how many color swatches you need. It automatically makes sure that the lightness varies evenly.

You’re probably wondering why I told you about colourspaces and colourblindness when all you need is a bit of JS. If you don’t understand the basics, this won’t work so well for you. You still need to know not to seed it with hues of similar lightness, or to pick red and green.

You can also change the mode to use the LAB space but the result will be a bit less vibrant, although that might be your jam. It can also get a bit better contrast.

chroma.scale(bezierColor) .domain([‘yellow’, ‘green’, ‘navy’]), 5) .correctLightness(true);

If you’re not into the palettes you’re getting, you can also create multi-colour scales using bezier interpolation (which is a fancy way to say smooth curves between points) and lightness correction to make sure that the colours stay equidistant in luminosity. You can use these to force the scale to go through another colour.

The bezier interpolations only run in the LAB space, so, again, less vibrant colours.

alert(“Be careful with charts with lots of colours!”);

Word of warning:

Chroma scales will help to give you palettes that are visually appealing, especially if you follow basic colour theory and use seed colours that occur in nature — sunsets, birds, flowers — that type of thing.

BUT: Because they’re a lightness scale, they’re not the maximum distribution across the space possible for both lightness AND hue. For most ranges, if you have more than 5 colours, you’ll start struggling with perceivable differences.

First step is always to see if you can simplify what you’re trying to communicate. More than 5 lines or bars often means you’re making something too complex. But if you’re really stuck, or if this is all sounding too hard…

Colorbrewer is your friend. Colorbrewer is a series of palettes designed by Cynthia Brewer for use in maps, but they also work well for other types of dataviz.

Screenshot from colorbrewer site showing palettes.

Colorbrewer does all the hard work for you, and you can even use the chroma.js library to grab the colour palettes and use them in your viz.

I’m not going to get into it here, but there’s also some basic principles about which style of colour scheme you should use for the type of data you’re trying to display — sequential, diverging, or qualitative. This is especially important for maps — you can get away with a bit more in chart form.

Charts from new Figure.NZ in all forms of colour blindness. You can see all the colours.

So this is what my work ended up with for all forms of colour blindness.

So, if we’ve got colour nailed, what are the other things?

Line charts are really the ones this is hardest for.

Economist chart with labels by each line.

First up, be smart about your legend labels. Having a separate legend means you rely on colour to transmit the meaning. Labelling the lines directly removes this requirement, and also reduces the cognitive load for all users by removing a layer of abstraction.

Otherwise, make sure your legend order is the same as the order of your lines at whichever end it’s located.

NZ Herald interactive with line highlighting.

You can also use interactivity to help by highlighting specific points. The ability to directly interact with a line and see the corresponding labels again removes reliance on colour alone.

This interactive from NZ Herald enables you to mouse-over and select points to examine. Of course, this isn’t very keyboard friendly, so has other accessibility challenges, and increases cognitive load if you want to compare multiple lines against one another as you have to remember which labels map to which lines.

Chart with dotted line style.

If you don’t have too many lines on a chart (although obviously more than one), you can use different line styles so that the form of the line communicates meaning as well as the colour.

This is built into D3 by default, which is what this snippet is here.

This won’t be suitable if the line has sharp peaks and troughs as it interferes with the readability of the data, but for simpler shapes without too many lines, it can work well. The same applies for point markers of different shapes — if it’s a simple dataset, you can use add a visible point for each data point and make them different shapes for each line.

Test things.

Perhaps most importantly, don’t leave this up to chance. Test things.

List of tools (outlined in text to the right of this)

Check if any of your colleagues are colourblind. There’s also a number of apps to emulate each state — I use Sim Daltonism and the Spectrum Chrome plugin.

Many colourblind users will also use Chrome’s High Contrast plugin, so check your viz with that enabled too.

What I want you to take away from this is two things:

  1. Do visualisations. They are excellent and fun and useful and really can help people understand and ask better questions, but
  2. Do inclusive visualisations. Once you understand the science, it’s easy to make visualisations that are inclusive of colour blind people. So do it!


🌏 📊 Around the world in 80 shades: Building color blind accessible dataviz 📊🌏 was originally published in Towards Data Science on Medium, where people are continuing the conversation by highlighting and responding to this story.