Build Accessible Color Palettes for Your UI
Picking colours for a UI is harder than it looks. A palette that looks great in a mockup can fall apart when you apply it to real components, test it in different lighting, or run it through an accessibility checker. Getting colour right means understanding the system before you start picking hues.
Start With One Base Colour
Every solid UI colour palette starts from a single anchor — usually your primary brand colour. From there you derive the full system using colour relationships. The relationships between colours matter more than the individual hues.
The three most practical relationships for UI design are complementary (opposite on the colour wheel), analogous (adjacent hues), and triadic (three equally spaced hues). Complementary creates strong contrast and energy. Analogous creates harmony. Triadic gives balance with variety.
The Colour Roles a UI Needs
A functional UI palette assigns a specific role to each colour — not just "this is blue" but "this is the colour used for primary interactive elements." That structure is what makes a palette feel intentional rather than arbitrary.
- Primary — main actions, active states, key interactive elements like buttons and links
- Secondary — supporting elements, accents, secondary actions
- Neutral — text, borders, backgrounds, and dividers (a complete grey scale is essential)
- Semantic — error (red), warning (amber), success (green), info (blue)
- Surface — card backgrounds, modal overlays, input fields
Building a Colour Scale
Most design systems do not use a single shade of each role colour — they use a scale of 9 to 11 values from lightest to darkest. This lets you use the light values for backgrounds, mid values for interactive elements, and dark values for text.
:root {
/* Primary scale */
--color-primary-50: #eff6ff; /* very light background tint */
--color-primary-100: #dbeafe;
--color-primary-300: #93c5fd;
--color-primary-500: #3b82f6; /* core brand colour */
--color-primary-700: #1d4ed8; /* hover states */
--color-primary-900: #1e3a8a; /* darkest — high-contrast text */
/* Semantic colours */
--color-error: #d32f2f;
--color-warning: #f57c00;
--color-success: #388e3c;
--color-info: #0288d1;
}
WCAG Contrast — Why It Is Non-Negotiable
WCAG (Web Content Accessibility Guidelines) defines minimum contrast ratios between text and its background. These exist because some users — those with low vision, colour blindness, or visual processing differences — literally cannot read content that does not meet the threshold.
- AA — Normal text: 4.5:1 minimum contrast ratio
- AA — Large text (18px+ or 14px+ bold): 3:1 minimum
- AA — UI components and icons: 3:1 minimum
- AAA — Enhanced: 7:1 for normal text (target for healthcare and accessibility-critical apps)
The CreativeUtil Color Palette Generator includes WCAG contrast analysis built in. You see immediately whether your colour combinations pass or fail before you ship anything — no separate checker needed.
Colour Blindness Considerations
Roughly 8% of men and 0.5% of women have some form of colour vision deficiency. The most common is red-green colour blindness, which affects how users distinguish your semantic colours — error (red) and success (green) can appear nearly identical.
Never rely on colour alone to communicate status or meaning. Always pair colour with iconography, text labels, or pattern. Your error state should say "Error" or show an X icon — the red colour is supplemental, not the primary signal.
Dark Mode Palettes
Dark mode is not just inverting your light palette. Colours that work in light mode often lose contrast or look oversaturated in dark mode. Build your dark palette separately using your colour scale, and test contrast ratios for both themes independently.
/* Light theme */
:root {
--bg-primary: #ffffff;
--text-primary: #1a1a2e;
--color-brand: #3a7abf;
}
/* Dark theme */
[data-theme="dark"] {
--bg-primary: #0f172a;
--text-primary: #e2e8f0;
--color-brand: #60a5fa; /* lighter shade for dark bg contrast */
}
Exporting for Your Design System
Once your palette is set, document it as CSS custom properties at the :root level. This creates a single source of truth that every component in your codebase references — change a value once and it updates everywhere.
:root {
--color-primary: #1a3c5e;
--color-primary-hover: #2b5f8e;
--color-secondary: #3a7abf;
--color-error: #d32f2f;
--color-success: #388e3c;
--color-text: #1a1a2e;
--color-text-muted: #64748b;
--color-border: #e2e8f0;
--color-bg: #ffffff;
--color-surface: #f8fafc;
}
Build Your Palette
Colour decisions made early shape every design decision that follows. Build your palette thoughtfully, test contrast rigorously, and document it as CSS variables from day one. Use the Color Palette Generator to generate, test for WCAG compliance, and export a palette ready to drop straight into your design system.
You Might Also Like
-
General • Feb, 2026
Stop Juggling Tabs: Meet CreativeUtil, Your All‑In‑One Utility Hub for Modern Web Developers & Designers
Simplify your workflow with CreativeUtil: 60+ free, privacy‑friendly browser tools for developers and designers. CSS, design, dev, and conversion tools in one place.
Read More -
General • Feb, 2026
Why I Built CreativeUtil: Solving My Own Web Dev Frustrations
The story behind CreativeUtil — how frustration with scattered, privacy-invasive tools led to building 43+ free, browser-based utilities for developers and designers.
Read More -
General • Feb, 2026
CSS Text Shadows That Actually Look Good
CSS text shadows done right: subtle lifts, glows, hard shadows, and layered depth — with code examples and a live generator to copy production-ready CSS instantly.
Read More -
General • Feb, 2026
How to Format and Validate JSON in Your Browser
Stop squinting at minified JSON. Format, validate, and debug any JSON payload instantly in your browser — no install, no server, no data sent anywhere.
Read More