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
- Network requests
- ·
- Our own script
- ·
Was this tool useful?
Why the contrast notes are the point
Exporting a palette to CSS variables is a find-and-replace with extra steps, and you could do it by hand in a few minutes. The export is not the point of this page.
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
How do I turn a color palette into CSS variables?
Paste one color per line, hex first, then the name you want. You'll get a :root block with one custom property per color, such as --bnv-accent-deep: #0E6B78;. Each line notes its contrast against your lightest and darkest colors. Change or clear the prefix under Name prefix. Pick SCSS variables or JSON tokens instead if you like, then copy or download.
How are the variable names made?
Each name is lowercased. Every run of characters other than a to z and 0 to 9 becomes a single hyphen, and hyphens at either end are dropped. So "accent deep" becomes --bnv-accent-deep. A name that starts with a digit gets color- in front, which turns "2nd brand" into --bnv-color-2nd-brand. When two different colors share a name, the second one gets -2 and the status line says so.
How do I add opacity to a CSS color variable?
Mix it with transparent. MDN's color-mix() page shows this pattern, and color-mix(in srgb, var(--bnv-accent) 50%, transparent) gives you the accent at half opacity. This page won't write alpha values itself. It outputs 6-digit hex, and it won't read an 8-digit code like #2FBFD080.
Can it read or write OKLCH, rgb() or Tailwind colors?
No. It reads hex only, 3 or 6 digits, and writes 6-digit hex. Lines with rgb() or oklch() aren't read. Neither are lines of existing CSS like --bnv-ink: #131A22;, because each entry has to start with the hex code. Output comes as CSS custom properties, SCSS variables or JSON. There's no Tailwind config.
Is there a dark mode block?
No. The output is one :root block for the colors you paste, with no dark variants and no prefers-color-scheme rule. For a dark theme, paste your dark colors as a second palette and set the prefix to dark, so ink becomes --dark-ink. Then point your variables at those inside your own @media (prefers-color-scheme: dark) rule or theme class.
Does this upload my palette?
No. The conversion runs in this tab, and Download file builds the file in the page. Before any update to this page goes live, an automated check types into every box and presses every button, and blocks the update if what it typed turns up in a request. A share link carries your palette after the # in the address, which browsers don't send to a server.
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.