The fundamentals

How to choose website colors: give every color a job

Start with what a color needs to do. A beautiful row of swatches becomes a useful website palette when you know which one is the page, the text, and the action.

Reviewed 7 October 2026 · 3 min read

Cobalt, yellow-green, ivory and black paper arranged in sculptural folds

An original AI-generated paper color study. The working palette uses the exact hex values below.

Start with one real screen

Pick a screen that contains the things your site actually needs: a heading, a paragraph, a link, a primary action, and a secondary panel. A palette that works on a logo may need different roles on a page full of text. Testing a realistic screen makes those needs visible early.

Choose a palette for its visual character, then treat its roles as a proposal. You can keep a favorite bright color without making it the body text or putting white labels on top of it.

Assign five simple roles

Cobalt & citrus: a worked example
RoleColorJob
Background#F5F6F0The main canvas
Surface#E7EAD9Secondary panels and cards
Text#20241DHeadings and body copy
Primary#3448C5The main action and text links
Accent#D5EC59Highlights and supporting fills

These are starting roles, not a complete design system. A form-heavy application may also need distinct error, success, warning, focus, and border tokens. Add them when the interface needs them, and test the actual combinations.

Check the pairs that will touch

In this example, text on the page background has 14.51:1 contrast. The primary blue on that same background has 6.71:1. Both meet the AA normal-text threshold of 4.5:1. The yellow-green accent on the background is only 1.21:1, so it should not carry small text there.

Put the accent behind a dark label instead: black on the yellow-green fill has 15.97:1. That lets you retain the character of the palette while giving the words a readable pairing. The standard applies to the foreground and background together, not to an isolated hex code. W3C explains the text contrast thresholds.

Make hierarchy with more than color

Use spacing, size, weight, position, and labels to make the reading order clear. A primary action can have a filled background and a clear verb. A secondary link can remain underlined. An error needs an explanation, not just a red outline.

A pale surface may look different enough for decorative grouping but still be insufficient as the sole visible boundary of a required control. Check essential component boundaries against their adjacent colors. W3C’s non-text contrast guidance describes the relevant 3:1 requirement and exceptions.

Name tokens for their purpose

Use --color-primary instead of --blue when the variable describes an action role. If the brand later changes, the name still makes sense. Give text on a colored fill its own token, such as --color-on-primary; it does not have to match the body text.

Our studio expands those starting roles into two independent themes with 12 named roles each, including links, secondary text, borders, focus rings, hover fills and black or white labels. Copy those tokens into your stylesheet, then check them on your actual components. Exporting colors does not automatically update existing CSS or audit a finished site.

A useful final pass

  1. Read a real paragraph at its intended size, including on the secondary surface.
  2. Check links, button labels, form boundaries, and focus indicators.
  3. Inspect hover, selected, error, and disabled states in their actual context.
  4. Use labels, shapes, or patterns wherever color communicates a difference.
  5. Review the page on a narrow screen and with enlarged text.

Keep the result focused: fewer intentional roles are easier to maintain than many nearly identical shades with no clear purpose.

Try the worked example

See Cobalt & citrus on a live interface, change any role, and check every pair.

Open Cobalt & citrus ↗

Our examples use original palette values and the WCAG 2.2 calculation. Full methodology and primary sources.

← All field notes