In practice

How many colors does a website color palette need?

Fewer than you think, and more than you planned. The gap between 'a palette' and 'a color system' is where most projects lose control.

Ask for a website color palette and you get five swatches. Build the product and you discover you need about sixty values. Both numbers are correct; they are answers to different questions.

The palette: three to five colors

For the identity, meaning what the brand looks like at a glance, three to five colors is right, and the split matters more than the count. The 60/30/10 color rule from interior design transfers unusually well:

  • 60% dominant. Almost always a near neutral. This is the page background and the large surfaces. If your dominant color is saturated, everything else has to fight it.
  • 30% secondary. Structure. Cards, headers, the navigation. Usually a darker or lighter step of the dominant.
  • 10% accent. The brand color. Buttons, links, the one thing you want clicked.

The proportions do the work. A single vivid teal at 10% of the surface area reads as confident; the same teal at 60% reads as a municipal website. Most palettes that “look cheap” are not badly chosen, they are badly proportioned.

The system: the ramps behind the palette

The moment you build components you need more than five values, and they are not new colors. They are steps of the ones you have:

  • Hover and active states for every interactive color
  • Disabled states
  • Borders, dividers, and three or four surface elevations
  • Focus rings
  • Four semantic statuses: success, warning, danger, info
  • A full neutral ramp, which is the most used color in any interface

That is where the ramp from 50 to 950 comes from. Nine to eleven steps per hue, generated rather than picked. Five hues at eleven steps is fifty five values, which sounds alarming until you remember nobody chooses them individually.

Generate, do not curate

Picking sixty values by hand guarantees inconsistency, because nobody can hold that many relationships in their head. Define the ladder once, apply it to each hue, and correct only the steps that genuinely need it.

Design system color tokens: two layers of naming

This is the part that determines whether your system survives contact with a redesign.

Layer one: primitives. Literal names for literal colors. --teal-500, --red-700. They describe the color and nothing else. They never appear in a component.

Layer two: semantics. Names for roles. These are what components use:

:root {
  /* primitives */
  --teal-500: #2f6f68;
  --teal-600: #245751;
  --gray-50:  #fbfaf8;
  --gray-900: #16191d;
  --red-600:  #a4362c;

  /* semantics */
  --surface:          var(--gray-50);
  --text-primary:     var(--gray-900);
  --action:           var(--teal-500);
  --action-hover:     var(--teal-600);
  --border-danger:    var(--red-600);
}

Now a rebrand is an edit to the primitives. Dark mode is a second block of semantic assignments. And when someone asks “can we make buttons purple”, the answer is a change to one line instead of a search for every occurrence of a hex code.

The rule that keeps it honest: a component may never reference a primitive directly. If a component needs a color that no semantic token covers, the answer is a new semantic token, not a raw value.

Building the set

A workable sequence:

  1. Fix the brand color. Usually given, rarely negotiable.
  2. Choose a neutral with a temperature. Pure gray is inert. A neutral carrying a few degrees of the brand hue makes the whole interface feel intentional. This is the single decision with the most leverage on the list.
  3. Add one accent using a harmony rule as the starting point. The color palette generator will do this and let you lock what works.
  4. Pull in four semantic colors. Do not invent these. Green for success and red for danger are almost universal conventions, and breaking them costs you comprehension for no gain.
  5. Generate the ramps. One ladder, applied to every hue.
  6. Test the pairs you will actually use. Not all of them, just the ones that will carry text. Fix any that fail by moving lightness only.

The subtraction test

When a palette is not working the instinct is to add a color. It is almost always the wrong move. Try removing one instead, and see whether anything was actually lost.

Most interfaces that feel noisy have too many colors doing the same job: three different blues where one would do, two grays a hair apart that nobody can distinguish and every developer picks between at random. Every color in the system should have a role you can name in a sentence. If you cannot name it, delete it.

Read next