Color That Works: Palettes and Contrast

A small palette (a brand color, neutrals, an accent, and success and error colors) makes a site look like one brand, and text that meets a contrast ratio of 4.5 to 1, with meaning never shown by color alone, makes it readable for everyone.

Journeyman · CSS · Web Development · Updated

After this lesson you can

  • Build a palette with a brand color, neutrals, an accent, and success and error colors
  • Check that text meets a contrast ratio of 4.5 to 1 with the developer tools' contrast checker
  • Show meaning with words or icons as well as color, never with color alone

Key takeaways

  • A palette is a short list of colors, each with a job, mostly neutrals for text and backgrounds, a brand color, one accent, and a success and an error color.
  • Contrast ratio compares how light two colors are, from 1 to 1 (the same) to 21 to 1 (black on white).
  • Body text needs a contrast ratio of at least 4.5 to 1 against its background. Large text needs at least 3 to 1.
  • The developer tools' color picker shows the contrast ratio of any text, and whether it passes.
  • Never let color alone carry a meaning. Add a word, an icon or an underline, so someone who can't see the color still gets it.

The market's board wants the website to use "the green from our banner". A shopper emails to say the light gray text is hard to read on her phone outdoors. A vendor's "Sold out" sign shows up in red, and a shopper who can't tell red from green walks to the booth anyway. Color comes up on every site you'll build: a brand guide that lists a company's colors, a class rubric that asks for "accessible color contrast", a report from a checking tool that flags your text in red. This lesson shows how to choose a small set of colors, how to measure whether text is readable, and the one rule that keeps color from shutting anyone out.

A palette: a few colors, each with a job

A sign shop doesn't stock every color of paint. It keeps a short row of cans it knows go together, and a sign made from that row looks finished. A palette is that row for a website: a short list of colors, each with a job. Most palettes need five kinds:

Job What it's for The market's choice
Brand the color people remember: headings, links, the main button market green #2f6b3a
Neutrals most of the page: text, quieter text, lines, backgrounds soil #2b2a26, stone #6b675e, linen #d8d2c4, cream #fbf8f1, white
Accent a second color for the one thing that must stand out sunflower #f2c14e
Success "it worked": a confirmed sign-up, "In stock" leaf #2e7d32
Error "something's wrong": a form mistake, "Sold out" tomato #b3261e

Notice how much of the palette is neutral. A page is mostly background and text, and those are calm colors; the brand and the accent are used sparingly, so they stand out when they appear. A rough guide designers use is 60-30-10: about 60% of the page in the main neutral, 30% in a second color, 10% in the accent.

body {
  background-color: #fbf8f1;
  color: #2b2a26;
}

h1, h2, a { color: #2f6b3a; }
.when { color: #6b675e; }
.vendor { background-color: #ffffff; border: 1px solid #d8d2c4; }
.notice { background-color: #f2c14e; }

Every color on the page now comes from the palette. Typing the same hex code in ten places invites a typo, and Custom Properties: Variables in CSS, the next chapter, names each color once.

Try it. Pick a business you like, such as a coffee shop, a bike shop or a game store, and write down a palette for it: one brand color, three neutrals, one accent, a success and an error color. Color: Names, Hex, rgb() and hsl() shows how hsl() gives you lighter and darker shades of one color for the neutrals.

Contrast ratio: how far apart two colors are

Gray letters on a gray sign are hard to read at dusk, even for someone with perfect eyesight. What matters is how different the letters and the board are in lightness. Contrast ratio puts a number on that: it compares how much light two colors give off, and it's written like 4.5:1, read "4.5 to 1".

  • 1 to 1 is no contrast at all: the same color on itself.
  • 21 to 1 is the most there is: black on white.
  • 4.5 to 1 is the minimum for body text.
  • 3 to 1 is the minimum for large text: about 1.5rem (24 pixels) and up, or about 1.2rem and up when it's bold. Bigger letters are easier to make out.

These numbers come from the WCAG, the Web Content Accessibility Guidelines, the rules most of the world uses for an accessible website. In your textbook, or in a job posting, 4.5 to 1 may be called WCAG AA: level AA is the level most laws and companies ask for. (Level AAA asks for 7 to 1.)

Here's how some real color pairs measure up:

Text on background Contrast ratio Body text?
soil #2b2a26 on cream #fbf8f1 13.54 to 1 passes
market green #2f6b3a on cream 6.03 to 1 passes
gray #767676 on white 4.54 to 1 passes, barely
gray #777777 on white 4.48 to 1 fails, barely
white on orange #d9531e 4.03 to 1 fails (large text passes)
light gray #a8a8a8 on white 2.38 to 1 fails
white on yellow #ffd400 1.43 to 1 fails badly

You can't judge this by eye: #777777 and #767676 look identical, and one passes while the other doesn't. You measure it.

/* Before: white on bright yellow, 1.43 to 1 */
.notice { background-color: #ffd400; color: #ffffff; }

/* After: dark soil on sunflower, 8.56 to 1 */
.notice { background-color: #f2c14e; color: #2b2a26; }

The fix kept the warm yellow and turned the text dark. When a light background fails, darken the text; when a dark one fails, lighten it.

The bag notice twice: white text on bright yellow that almost disappears, labeled 1.43 to 1, fails; and dark text on a golden yellow that reads clearly, labeled 8.56 to 1, passes

The contrast checker in the developer tools

You don't need to work out a ratio by hand: the browser does it for you.

  1. Open the page with Live Server, right-click some text and choose Inspect. The developer tools open with that element selected.
  2. In the Styles pane, find the color declaration and click the small color square beside its value. A color picker opens.
  3. In Chrome and Edge, the picker has a Contrast ratio line: the ratio against the background, with a check mark when it passes and a warning sign when it doesn't. Click it to see the AA and AAA levels. Lines drawn across the picker's color area show where the passing colors begin, so you can drag the color to a passing spot.

Two more ways to see it: hover over text with the Inspect arrow, and the label that pops up shows Contrast with a check mark or a warning. In Firefox, open the Accessibility panel and choose Check for issues, then Contrast, to list every piece of text that fails.

The developer tools' color picker open on the market page's quiet gray text, showing a contrast ratio of 5.31 with a check mark and two lines across the color area where AA and AAA begin

Try it. Give your market page's .when line the color #a8a8a8. Open its color picker in the developer tools and read the contrast ratio. Then drag the color darker until the warning becomes a check mark, and copy the new hex code back into your stylesheet.

Never color alone

About 1 man in 12, and 1 woman in 200, sees some colors differently, most often red and green. A traffic light handles this well: stop is always on top and go is always on the bottom, so a driver who can't tell the colors apart still knows which light is lit. Color helps, but the position carries the meaning too.

Your pages need the same backup. The rule: never let color alone carry a meaning. Add a word, an icon, a pattern or an underline. On the market's page, a vendor who has sold out was shown only with a red border:

<article class="vendor sold-out">
  <h3>Hilltop Honey</h3>
  <p class="status">Sold out for today</p>
  <p>Raw wildflower honey and beeswax candles. Booth 4.</p>
</article>
.sold-out { border-left: 4px solid #b3261e; }
.status { color: #b3261e; font-weight: 700; }

The red border is still there, and now the words "Sold out for today" say it for anyone who can't see the red, or who uses a screen reader, which reads the words and never the color. The same rule covers more of the page:

  • Links in a paragraph keep their underline. Color alone can't tell a link from the words around it.
  • A form mistake gets a message, such as "Enter an email address", not only a red border.
  • A chart or map gets labels or patterns, not only colored areas.

Try it. Turn your browser's view to grayscale. In Chrome and Edge, open the developer tools, press Ctrl+Shift+P (Cmd+Shift+P on a Mac), type Rendering, choose Show Rendering, then pick Achromatopsia under Emulate vision deficiencies. Is there anything on your page you can no longer understand?

Check yourself

2 questions to try on the lesson page.

So what

A small palette makes a site look like one brand, and contrast you've measured makes sure everyone can read it. Both are things a checking tool, a client or a grader will look for, and now you can find and fix them in a couple of minutes.

Key terms

Cheat sheets

Related