Skip to content
ZeroServer.tools

CSS Variables Generator

Generate a 10-shade CSS custom property scale from any base color.

Base Color: #6366f1Variable Prefix: --primaryShades Generated: 10HSL Base: 239°, 84%, 67%
Presets:
Base color
Variable prefix name
CSS output
:root {
  --primary-50: #e8e8fd;
  --primary-100: #c7c8fa;
  --primary-200: #9899f6;
  --primary-300: #6467f2;
  --primary-400: #3538ed;
  --primary-500: #1317dd;
  --primary-600: #0f12ae;
  --primary-700: #0b0d83;
  --primary-800: #080959;
  --primary-900: #040534;
}
Shades Preview
50
#e8e8fd
100
#c7c8fa
200
#9899f6
300
#6467f2
400
#3538ed
500
#1317dd
600
#0f12ae
700
#0b0d83
800
#080959
900
#040534

CSS custom properties for design tokens

CSS custom properties (CSS variables) are the foundation of modern design tokens — defining your palette once in :root and reusing var(--primary-500) everywhere. This generator produces a 10-shade scale (50–900) at fixed lightness steps, keeping hue and saturation constant — the same approach used by Tailwind CSS and most design systems. Swap the base color to instantly retheme the whole palette. For a visual side-by-side comparison, try the Color Shades Generator, or generate a full multi-color palette with the Color Palette Generator.

Built and maintained by Meet Shah · Last updated

What this tool is used for

  • Producing a ten-shade scale from one base colour as custom properties.
  • Generating a token set for a new colour in an existing system.
  • Adding a new brand colour to a system that already has shade steps for the others.
  • Getting light and dark steps around a brand colour.
  • Replacing hand-picked shades with a consistent scale.

How it works in practice

A worked example

A brand colour needs a full ten-step scale as custom properties, the way a design system numbers them.

Input
Base colour  #6366f1
Name         primary
Output
:root {
  --primary-50: #e8e8fd;
  --primary-100: #c7c8fa;
  --primary-200: #9899f6;
  --primary-300: #6467f2;
  --primary-400: #3538ed;
  --primary-500: #1317dd;
  --primary-600: #0f12ae;
  --primary-700: #0b0d83;
  --primary-800: #080959;
  --primary-900: #040534;
}

The hue and the saturation are taken from the colour you gave and held constant; only the lightness moves, through ten fixed stops from 95 percent down to 11. That is what makes a scale look like one family rather than ten unrelated colours, and it is why the numbering is worth adopting even for a single accent — a component that references the 700 for text and the 100 for its background keeps working when the base colour is swapped for another one.

The edge case that catches people

Look for your colour in that list and it is not the 500. The base was #6366f1, whose own lightness is 67 percent, so it lands on the 300 stop — and the 500 is markedly darker than the colour anyone typed. Scales published by design systems usually put the brand colour at the 500 by construction, so a generated scale and a hand-tuned one disagree about what the middle means. Read the number as a lightness step rather than as a distance from your colour, and pick the stop that matches rather than assuming.

When not to use this tool

Fixed lightness steps are not perceptually even, which is the limitation to know before shipping a palette built this way. The same numeric step looks like a much bigger jump in a yellow than in a blue, because that model treats all hues as equally bright at a given lightness and the eye does not — so a scale generated for one hue and reused for another will read as uneven. A perceptual space is the modern answer, and either way a text-on-background pair from any two stops still has to be measured for contrast rather than assumed from the numbers.

Frequently Asked Questions

Why declare variables on :root?
Because it is the document root with a slightly higher specificity than `html`, and everything inherits from it. A token defined there is available everywhere and is harder to override by accident, which is what makes one redefinition swap a whole theme.
How does a fallback work?
`var(--brand, #333)` uses the second value when the first is unset. Without one, an undefined variable makes the entire declaration invalid at computed-value time — so the property falls back to its inherited value rather than to the previous rule, which is worse than being ignored.
Can custom properties hold anything?
Almost — the value is substituted as a token stream, so a variable can hold a whole shorthand, a partial value, or even a fragment that is only valid once combined. That flexibility is why an invalid substitution is only detected at use time, not at declaration.
Are they case-sensitive?
Yes, unlike nearly everything else in CSS. `--mainColor` and `--maincolor` are two separate properties, so mixing conventions creates bugs that survive code review. Kebab-case throughout is the usual defence.
Can JavaScript read and write them?
Yes — `getComputedStyle(el).getPropertyValue('--x')` reads and `el.style.setProperty('--x', v)` writes. That runtime access is the whole difference from a preprocessor variable, and it is how theme switching works without shipping two stylesheets.

Common errors and gotchas

  • Generating a scale without checking contrast at each step.
  • Naming shades by number and then needing to insert one between two.
  • Producing steps that are numerically even but perceptually uneven.
  • Adopting the scale without migrating existing values, so both coexist.
  • Defining the variables only under a theme selector, leaving them undefined by default.

Related Design & CSS tools

Private & free — this tool runs entirely in your browser.

KinstaFast managed hosting — up to $500 + 10% recurring.affiliate