Benchvale

Palette to CSS variables

This turns a pasted color palette into CSS custom properties, SCSS variables or a JSON token file. It also carries each color's contrast ratio into the output as a comment, so the file that lands in your codebase records which pairs were checked and which ones failed. All three formats, free, no account.

Your palette

Measured on this page, in this browser
Requests
· from Resource Timing
Script
· KB of a 100 KB budget
Everything here runs in your browser. We never send your palette to ourselves or anywhere else. It stays on your device. Once the page has loaded, you can disconnect and keep working. How we build tools

Why the contrast notes are the point

Exporting a palette to CSS variables is a find-and-replace with extra steps. Half a dozen tools do it and it takes four minutes by hand. That is not what this page is for.

The useful part is what the file remembers. A token file that arrives as eight hex values tells the next developer nothing about which combinations are safe, so they pick two that look nice and ship a 2.8:1 label. A token file that arrives with /* on paper 5.12:1 AA, on ink 3.19:1 Fail */ next to each color answers the question at the moment it gets asked, which is while somebody is writing the CSS, not during an audit six months later.

The notes compare each color against the lightest and darkest colors in the palette, because that is what a palette actually gets used as: something dark for text on something light, and the reverse. For every pair rather than the two extremes, use the contrast grid.

Naming

Names become the variable names, lowercased with anything that is not a letter or a digit turned into a hyphen. "accent deep" becomes --bnv-accent-deep.

Two different colors that slug to the same name are a collision, not a duplicate. The first keeps the name; later ones get a numeric suffix such as --bnv-brand-red-2 and the status line names the collision so nothing is silently overwritten. Identical hex and name on two lines still collapses to one entry, which is the correct duplicate.

A name that starts with a digit or is only punctuation would produce a custom property that does not parse, so those get a color- prefix rather than being emitted broken. It is a small thing that turns a file which silently fails to apply into one that works.

Worth saying because it is the most common regret in a design system: name colors for what they are, not what they currently do. --brand-blue survives a redesign. --button-color becomes a lie the first time a button changes.

Three formats, one paste

CSS custom properties are the default because they are the only one that works at run time, which is what you want for a theme switch or dark mode. SCSS variables are compile time and cannot be swapped in the browser, but they are still what a lot of existing codebases are built on.

The JSON output is a flat token file, which is the shape most design token pipelines accept as a starting point. It is deliberately simple rather than being any particular vendor's schema, because converting simple JSON to a specific format is easy and converting one vendor's format to another is not.

Questions

Does this upload my palette?

No. The conversion is string handling and it runs in your browser. Even the download button builds the file in the page rather than fetching it from anywhere. Once the page has loaded, you can turn off your wifi and it all still works.

What do the contrast notes compare against?

The lightest and the darkest color in the palette you pasted, at the 4.5:1 normal-text threshold. Those two are the ones nearly everything ends up sitting on. They are not every pair, and if you need every pair the grid is the tool for it.

Can I paste CSS I already have?

Yes. It splits on line breaks, commas and semicolons and picks the hex value out of each chunk, so pasting an existing block of custom properties mostly works. It reads hex only, so rgb() and hsl() values are skipped rather than misread.

Why is there no dark mode block in the output?

Because a dark theme is a second palette, not a transformation of the first one. Tools that generate one by inverting lightness produce something that technically contrasts and looks wrong, since the colors that read as calm on white read as muddy on near-black. Build the dark palette deliberately and export it as its own set.

Related tools

Before exporting, check the whole set with the palette contrast grid, or a single pair with the contrast checker. Worth also running it through the color blindness simulator, since contrast and hue are separate problems and passing one says nothing about the other.

Maintained by Aaron Wilson
Published . Last updated . Method and formula: how we build tools. Something wrong? Tell us and it goes in the changelog.