DTTooleras

How to Build a Color System for Your Design: A Developer Guide

Learn how to create a consistent, accessible color system for your web application — from choosing a base color to generating a full palette with tints, shades, and semantic colors.

DevToolsHub Team18 min read476 words

Why You Need a Color System

A color system ensures visual consistency across your entire application. Without one, you end up with dozens of slightly different grays, blues, and greens scattered across your CSS — making maintenance a nightmare and accessibility impossible to verify.

Step 1: Choose Your Base Colors

Every color system starts with a few base colors:

  • Primary — Your brand color, used for buttons, links, and key actions
  • Neutral — Grays for text, borders, and backgrounds
  • Success — Green for positive states
  • Warning — Yellow/orange for caution
  • Error — Red for errors and destructive actions

Use our Color Picker to explore colors, or our Color Palette Generator to find harmonious combinations.

Step 2: Generate a Scale

For each base color, generate a scale of 10 shades from light to dark:

:root {
  --blue-50:  #eff6ff;
  --blue-100: #dbeafe;
  --blue-200: #bfdbfe;
  --blue-300: #93c5fd;
  --blue-400: #60a5fa;
  --blue-500: #3b82f6;  /* Base */
  --blue-600: #2563eb;
  --blue-700: #1d4ed8;
  --blue-800: #1e40af;
  --blue-900: #1e3a8a;
  --blue-950: #172554;
}

Use our Color Shades Generator to create these scales from any base color.

Step 3: Define Semantic Tokens

Map your color scale to semantic purposes:

:root {
  /* Text */
  --text-primary: var(--gray-900);
  --text-secondary: var(--gray-600);
  --text-muted: var(--gray-400);

  /* Backgrounds */
  --bg-primary: #ffffff;
  --bg-secondary: var(--gray-50);
  --bg-tertiary: var(--gray-100);

  /* Borders */
  --border-primary: var(--gray-200);
  --border-secondary: var(--gray-300);

  /* Interactive */
  --accent: var(--blue-600);
  --accent-hover: var(--blue-700);
  --accent-muted: var(--blue-50);
}

Step 4: Ensure Accessibility

Every text/background combination must meet WCAG contrast requirements:

  • Normal text: 4.5:1 minimum (AA)
  • Large text: 3:1 minimum (AA)
  • Enhanced: 7:1 (AAA)

Use our Color Contrast Checker to verify every combination.

Common mistakes:

  • Gray text on white background often fails (need at least #767676 for AA)
  • Colored text on colored backgrounds (check both light and dark modes)
  • Placeholder text that's too light to read

Step 5: Dark Mode

For dark mode, don't just invert colors. Create a separate set of tokens:

.dark {
  --text-primary: var(--gray-100);
  --text-secondary: var(--gray-400);
  --bg-primary: var(--gray-950);
  --bg-secondary: var(--gray-900);
  --border-primary: var(--gray-800);
  --accent: var(--blue-400);  /* Lighter in dark mode */
}

Step 6: Implement in CSS

/* Use semantic tokens everywhere */
.button {
  background: var(--accent);
  color: white;
}

.button:hover {
  background: var(--accent-hover);
}

.card {
  background: var(--bg-primary);
  border: 1px solid var(--border-primary);
  color: var(--text-primary);
}

/* Never use raw color values in components */
/* ❌ Bad */
.card { border-color: #e5e7eb; }
/* ✅ Good */
.card { border-color: var(--border-primary); }

Related Tools

color systemdesign systemcolor palettecss variablesdark modeaccessibilitywcagcolor tokens

Related articles

All articles

Practice with free tools

200+ free developer tools that run in your browser.

Browse all tools →