Design Trends

Pick the Wrong Brand Primary and the Whole Design System Breaks: Growing an 11-Step Palette From One Color

2026.09.10 · 70 views
Pick the Wrong Brand Primary and the Whole Design System Breaks: Growing an 11-Step Palette From One Color

Generate ramps in OKLCH, verify against WCAG 2.2, ship as design tokens in Tailwind — with five real brand cases and honest build-cost numbers

Share:

A primary colour is not a colour — it is the seed of a system

Most brand primaries are decided in a pitch deck: dark background, one big colour block, a few lines of white type. The problem surfaces three months later, when engineers need that colour for CTA fills, links, hover states, focus rings, chart series and error states — and it has to hold up on white and on grey. That is when the cracks show: one hex value, failing contrast at body-text size, primary and secondary buttons that look identical. This piece is not about which colours are trending. It is about choosing a primary that can actually grow a ramp, and turning it into a deliverable palette.

Five publicly observable cases

  • Stripe: a blue-violet (commonly published as #635BFF) appears only in CTAs, links and hero gradients, over a white site with generous whitespace. It scores about 4.7:1 on white — just past the 4.5:1 body-text threshold with almost no headroom, which is exactly why it never carries long-form copy.
  • Klarna: a fintech running pink (commonly published as #FFA8CD) against category convention. That pink hits only about 1.79:1 on white but roughly 11.7:1 against black — so pink panels always carry dark type. Not a stylistic preference; the only workable option.
  • Shopee: the brand orange (commonly published as #EE4D2D) measures about 3.66:1 on white. It clears the 3:1 bar for large text and UI components but fails 4.5:1 for body copy. So orange stays on buttons, prices and promo tags — large, short elements — while body copy is dark grey.
  • Notion: the interface chrome is close to achromatic; saturation is deliberately reserved for the user's own content (highlights, callouts, database tags). For a tool, handing chroma to the content is a clear trade.
  • Cathay Financial Holdings: a deep-green identity. Dark greens are structurally advantaged — a same-family #006B54 lands around 6.5:1 on white, so it works directly for body copy, links and table headers. Far more freedom than a bright, high-chroma primary.

The logic: three constraints pulling against each other

Choosing a primary means resolving a three-way conflict. Accessibility: WCAG 2.2 asks for 4.5:1 on body text and 3:1 on large text, while 1.4.11 Non-text Contrast requires at least 3:1 for button boundaries, icons and focus indicators. Salience: the von Restorff effect says the one element that differs from its surroundings is the one people remember and click, so the primary should be the only high-chroma block on the page — the moment secondary buttons share it, the effect collapses. Category convention: finance leans blue-green, dining leans warm; convention lowers cognitive cost but makes you resemble your competitor. Satisfying all three is not about picking a pretty colour, it is about picking a hue that can generate a complete ramp. Hence OKLCH: HSL's L does not map to perceived lightness (at L=50%, yellow reads far brighter than blue), whereas OKLCH's L does. Lock hue and chroma, move only L, and the ramp comes out evenly spaced and predictable.

Technical cost and limits

A full palette — 11 brand steps, 11 greys, plus five steps each for success, warning and error — takes us 12 to 20 hours end to end: generation, contrast sign-off, wiring into the Tailwind theme, aligning with Figma Variables. A one-off cost. File cost is negligible: around 60 CSS custom properties is 2–4 KB uncompressed and under 1 KB gzipped. What hurts performance is never the colour — it is the large bitmap added to fake a gradient or glow. A 1920px-wide gradient PNG easily exceeds 300 KB and, above the fold, drags LCP down directly; a CSS gradient costs zero bytes. Large-area backdrop-filter also drops frames noticeably on mid- and low-tier Android. On SEO: colour is not a ranking factor, but Lighthouse's Accessibility score penalises contrast failures outright. The most underestimated cost is SVG icons with hard-coded fills, which must all be re-exported on a colour change — switch them to currentColor and that bill disappears.

Which industries suit a bold primary — and which do not

Suits high chroma, bold primariesBetter served by restraint
D2C consumer goods, beauty and skincareB2B SaaS back-offices (long dwell time)
Dining and grocery e-commerceHealthcare and diagnostic report interfaces
Promotion-driven retail, events and ticketingTrading and order-entry interfaces
Games, children's and family educationData-visualisation products (save the ramp for data)
Personal brands and creative studiosGovernment tenders (strict accessibility sign-off)

The test is simple: the longer users stay and the more consequential their decisions, the further the primary should retreat. Push chroma only when you need to be remembered in three seconds.

How to apply it: seven steps

  • Define the jobs before the colour: list what the primary must do (CTA fill, links, focus ring, charts, brand blocks). Fewer than three jobs and you do not need a full ramp.
  • Anchor and generate in OKLCH: convert the candidate to oklch(), lock hue and chroma, move only lightness, and produce 11 steps from 50 to 950.
  • Run three contrast checks: primary fill with white text, white background with primary text, white background with a primary border (components need only 3:1). If one fails, change the step — not the hue.
  • Prepare a text-only dark variant: step 500 for brand blocks, 700 or 800 for links and copy. They were never meant to be the same value.
  • Add a semantic token layer: components should not consume brand-500 directly. Put --color-action-bg, --color-link and --color-focus in between so a rebrand touches one layer.
  • Tint the greys with the brand hue: give neutrals 2–4% of the primary's chroma so coloured components do not look pasted onto dead grey.
  • Test in three environments: a phone in direct sunlight, a projector, and Chrome DevTools' Rendering panel with vision-deficiency emulation on.

Common mistakes and how to avoid them

  • Handing over a single hex: with no hover, active or disabled steps, engineers resort to filter: brightness() and every page ends up slightly different.
  • Building ramps in HSL: at identical L values a yellow ramp reads far lighter than a blue one and the rhythm breaks. Use OKLCH, or start from the Tailwind default palette, already defined in OKLCH.
  • Encoding state in colour alone: red for error, green for success carries no information for users with red-green colour vision deficiency and violates WCAG 1.4.1. Triple-encode: colour plus icon plus text.
  • Flooding the page with the primary: the more surface it covers, the less a CTA reads as a CTA. Aim for 60/30/10 — neutral 60, secondary 30, primary 10.

Further resources

  • oklch.com — an OKLCH picker that flags in real time when a value falls outside sRGB or P3. The fastest way to build a ramp.
  • WebAIM Contrast Checker — the quickest contrast sign-off, with AA/AAA pass indicators.
  • Adobe Color — includes accessibility tools that simulate three types of colour blindness.
  • Coolors — fast exploration and export of palette combinations.
  • MDN: oklch() — syntax and browser support reference.

FAQ

Does the primary always have to clear 4.5:1?

It depends on the job. As a button fill or a heading at 18.66px bold and above, 3:1 satisfies AA; only 14px body copy and links require 4.5:1. Do not force one value to do both — keep a lighter variant for blocks and a darker one for text.

My logo colour fails contrast. Do I need to redesign the logo?

No. WCAG explicitly exempts logotypes from text contrast requirements. What you need to add is a darker interface variant so links and copy have a compliant value to use.

Can I use OKLCH in production today?

Yes. It is part of CSS Color Level 4 and has been supported across the last several major browser versions. To cover older environments, emit a hex fallback from your build tool or wrap the rules in @supports.

How many steps does a palette need?

Eleven (50 to 950) is the safe default: light steps for backgrounds and hover fills, mid steps for brand identity, dark steps for text and borders. A simple marketing site can live with five, but you need at least three layers — background, brand, text.

How long does changing the primary on a live site take?

It depends on whether a semantic token layer exists. With one, usually a day including regression testing. Without one, the colour is scattered across CSS, SVGs, email templates and the admin panel, and hunting down every instance typically takes three to five days.

Want your brand colour turned into a deliverable system?

ScriptWalker does design and engineering under one roof. We take your primary, grow it into a full ramp that passes WCAG 2.2 sign-off, and deliver design tokens, a Tailwind configuration and Figma Variables — so marketing pages, product UI and the mobile app read from one definition. If you would like a colour and contrast audit of your existing site first, get in touch:

Share:
Design Trends Back to Blog