Colour CSS

CSS colour variables generator

--brand: #5b8def;
--ink: #0f172a;
--radius: 8px;
--space: 16px;

Generated in your browser · nothing is uploaded

Local · names normalised to valid identifiers

Turns a list of name-and-value pairs into a :root block of CSS custom properties, normalising the names to valid identifiers and taking an optional prefix.

How to use the css colour variables generator

1 Paste one name and one value per line, straight out of a design file if that is where the palette lives.
2 Separate them with a colon, an equals sign, or just a space; a name of several words still works.
3 Add a prefix if your project namespaces its properties.
4 Copy the :root block, and note that every name has been lowercased on the way through.

Custom properties are not Sass variables under a different name, and the difference is the whole reason to reach for them. A Sass variable is substituted at build time and then no longer exists; the browser never sees it. A custom property is a live value in the cascade. It inherits down the tree, so redefining --surface on one section restyles everything inside it. It can be read and written from JavaScript with getPropertyValue and setProperty. It can be redefined inside a media query, a container query or a [data-theme] attribute selector. A dark mode built on custom properties is a dozen redefined values rather than a duplicated stylesheet, and that is a consequence of the cascade rather than a trick.

Name them for their role and not their appearance. --brand-blue becomes a lie the first time the brand stops being blue, while --brand simply keeps working. The same argument separates --grey-100 from --surface: one describes what the value is and the other describes the job it does, and only the second survives a redesign. A useful compromise on a large system is two layers, a small set of raw values named for what they are and a set of role names pointing at them, so --surface: var(--grey-100) is the only line that changes when the palette shifts.

Two mechanical details are worth having straight. Custom property names are case-sensitive, so --Brand and --brand are genuinely two different properties, and this generator lowercases every name it writes. If your palette arrives in title case, the output is the version to use throughout, because a var(--Brand) elsewhere in the stylesheet will not find it. Anything that is not a letter, digit or hyphen becomes a hyphen, a leading -- you paste in is stripped rather than doubled, and a line with no colon or equals sign is split at its last space, so Brand Primary #f00 comes out as --brand-primary: #f00.

The failure mode to recognise is a rule that looks like it vanished. A normal invalid declaration is thrown away at parse time and the previous cascade value survives. A declaration containing var() cannot be checked that early, because the substitution happens later, so an invalid result is only discovered afterwards. At that point the property does not fall back to what it was: it becomes invalid at computed-value time and takes its inherited value if it inherits, or its initial value if it does not. Supplying a fallback inside the function, as var(--brand, #333), is how you keep control of that.

What people use it for

  • Turning a palette handed over as a list of names and hex codes into a stylesheet
  • Renaming value-based tokens to role-based ones in one pass
  • Setting up the names a dark mode will redefine later
  • Adding a project prefix to every custom property at once
  • Getting a designer’s colour list into code without retyping it

Questions

Sass variables are substituted at build time and never reach the browser. Custom properties are live in the cascade: they inherit, they can be changed at runtime from JavaScript, and they can be redefined inside a media query.

MDN, Custom properties
Was this tool any good?
Internal signal only · I use it to find the tools worth rebuilding