Choose a Website Colour Palette: Practical Guide

A website palette is not a row of attractive swatches. It is a small set of colour decisions that helps people read content, recognise actions, understand status and move through an interface. Start with what each colour must do, then test it in the pages and states where it will actually appear. This produces a more coherent result than picking a ‘main colour’ and adding accents until the page feels busy.

Start with the interface’s jobs

List the moments where colour will carry useful meaning before choosing exact hex values. Most websites need a page surface, a second surface for panels, primary text, muted text, an interactive link or action colour, a focus indicator, and success and error treatments. A shop may add a sale label; a product dashboard may add warning and data-series colours. Keep these needs separate from decorative illustration colours.

Write a one-line purpose for every proposed role. For example: ‘primary action is used for the one next step on a page’; ‘muted text supports metadata, never essential instructions’; and ‘error appears with an icon and explanatory copy’. This exposes an early problem: one vivid accent cannot safely serve as a button fill, body-text link, chart line and validation state without careful pairing.

Choose a visual direction from the content, audience expectations and existing assets, not from claims that a hue always creates a particular response. An architecture portfolio might need quiet surfaces so project photography remains prominent. A booking flow needs a clear action hierarchy and obvious form feedback. Look at the logo, images, illustrations and product screenshots together, then choose colours that make those assets easier to use.

Build a small functional system

Begin with five to eight working roles, not five unrelated colours. A useful light-interface starter system is:

  • surface: the main page background;
  • surface-subtle: cards, grouped filters or secondary panels;
  • text: headings and body copy;
  • action and on-action: a filled primary control and the text or icon on it;
  • link: inline links and secondary interactive text;
  • success and error: named status roles, always supported by words and an icon where the state matters.

Primary, secondary and tertiary should describe emphasis, not a decorative ranking of swatches. The primary role is for the most important repeated actions. Secondary and tertiary roles offer lower or specialised emphasis. That distinction prevents every badge, button and chart series from competing for attention.

Use neutrals deliberately. A dark text colour, two or three surfaces and a restrained border tone usually create more useful hierarchy than several extra accents. If a palette feels flat, first adjust lightness between surfaces and text before introducing another saturated colour. If it feels noisy, reduce the number of roles visible in one component.

Choose colours in real page contexts

Test early swatches in a mini page, not only in a palette generator. Make one realistic section with a heading, two paragraphs, an inline link, a filled button, a disabled control, a form error, a success message and a card on a secondary surface. Repeat the exercise for the densest view in the product, such as a pricing table or settings screen. A colour that looks balanced as a large square may disappear when used as 14px text or a one-pixel border.

Use accent colours sparingly and give them a repeatable job. For instance, a blue may be the interactive colour, while a green and red are reserved for labelled states. Do not make green mean ‘good’ and red mean ‘bad’ without supporting text such as ‘Payment successful’ or ‘Card number needs attention’. Include an icon, text, pattern or position as a second cue. Colour may reinforce a message, but it should not be the only way to distinguish one.

For internal inspiration, compare how a dark product system such as Midnight SaaS handles a bright accent against a deep surface, then contrast it with the calmer structure of Architecture Desk. Browse the Modern SaaS and Creative Workspaces categories for additional directions. Brand guides such as Stripe and Apple are editorial references only. They are not official standards and are not endorsed by the brands named.

Check contrast before calling a pair usable

For normal text, WCAG 2.2 Level AA sets a minimum contrast ratio of 4.5:1 against its background. Large text can use 3:1, where large means at least 18pt regular or 14pt bold. Treat those as minimum checks, not permission to make essential text faint. Assess the actual foreground-background pairs that occur in the interface, including hover, selected, disabled and error states. Set both text and background colours explicitly for any pair you evaluate.

Here is a copyable, light-site example. The figures are relative-luminance contrast ratios calculated for the stated pairs:

  • #102A43 text on #FFFFFF: 14.64:1.
  • #FFFFFF on a #005FCC action fill: 5.98:1.
  • #FFFFFF on a #14532D success fill: 9.11:1.
  • #FFFFFF on a #B91C1C error fill: 6.47:1.

All four stated pairs exceed 4.5:1, so they are suitable for normal-sized text under that criterion. That does not automatically validate every use of those colours. A blue link still needs to stand apart from surrounding body text, and a success state still needs a visible label or icon. Check component edges, focus indicators and icons too; low-contrast outlines are easy to miss even when the label is readable.

Turn swatches into maintainable tokens

Name variables after their role rather than their appearance. --action can change from blue to plum without forcing a misleading rename throughout the codebase. CSS custom properties centralise repeated values and make an approved palette easier to apply consistently.

:root {
  --surface: #FFFFFF;
  --surface-subtle: #F1F5F9;
  --text: #102A43;
  --link: #005FCC;
  --action: #005FCC;
  --on-action: #FFFFFF;
  --success: #14532D;
  --error: #B91C1C;
}

body { background: var(--surface); color: var(--text); }
a { color: var(--link); text-decoration: underline; }
.button-primary { background: var(--action); color: var(--on-action); }

Use the same role names in design files, content guidelines and code. Document the permitted pair beside each token, for example on-action only on action. When adding dark mode, define another complete set of role values rather than inverting individual components ad hoc. Review a representative page at common zoom levels and on a phone outdoors if possible. A final visual pass catches collisions with photos, translucent overlays and browser defaults that a swatch sheet cannot show.

Avoid the common palette traps

  • Do not treat a logo colour as body text by default. Brand colours are often too light or vivid for small copy on white.
  • Do not use pale grey for essential instructions merely because it looks understated. Give secondary copy enough contrast for its size and background.
  • Do not make every button a different accent. Limit high-emphasis fills to preserve a clear next action.
  • Do not rely on colour alone for required fields, errors, selected states or chart categories.
  • Do not approve a palette from a desktop mock-up only. Test responsive, hover, focus, active, disabled and empty states.

If you need another starting point, compare the restrained Axiom, the panel-led Cloud Console, the dark Night Mode Studio and the pared-back Monochrome Luxe. Use them as prompts for role-based testing, not as a substitute for it.

Further reading

Run every intended pair through the Contrast Checker, then explore the Minimal & Monochrome category to find a focused starting palette.

Related guides

Suggested palettes

All guides All palettes