Material Color Palette Generator
A tonal palette from one colour, the Material 3 way, with the contrast at every step and an honest note about what Material 2's hand-picked palettes were.
Source #1e56ec · oklch(52.1% 0.233 264.0)
Scale Material 2 names, 50 to 900
Chroma 100% of the source
50 #e6efff tone 95 chroma 0.025 black text 18.16:1
100 #cedeff tone 90 chroma 0.049 black text 15.52:1
200 #9dbdff tone 80 chroma 0.101 black text 11.16:1
300 #6c9aff tone 70 chroma 0.157 black text 7.70:1
400 #3a73ff tone 60 chroma 0.217 black text 5.08:1
500 * #1e56ec tone 52 chroma 0.233 white text 5.84:1
600 #0a3dd3 tone 45 chroma 0.233 white text 8.01:1
700 #0029c2 tone 40 chroma 0.233 white text 10.02:1
800 #000094 tone 30 chroma 0.209 white text 14.71:1
900 #000054 tone 20 chroma 0.141 white text 18.62:1
CSS
:root {
--brand-50: #e6efff;
--brand-100: #cedeff;
--brand-200: #9dbdff;
--brand-300: #6c9aff;
--brand-400: #3a73ff;
--brand-500: #1e56ec;
--brand-600: #0a3dd3;
--brand-700: #0029c2;
--brand-800: #000094;
--brand-900: #000054;
}
The 500 step marked with an asterisk is your colour at its own tone, so
the palette is built around what you gave it rather than around a nearby
colour. The rest are the same hue and chroma at fixed tones.
Material 2's published palettes were hand-picked, so no formula
reproduces them and this does not claim to. Material 3's palettes are
tonal and algorithmic, which is what this follows: hold the hue and the
chroma, step the tone.
The tone here is OKLCH lightness rather than Material's HCT tone. Both
are perceptual and they agree within a couple of points, which is close
enough for a UI palette and not close enough to match Google's own
output digit for digit. OKLCH is the one you can write in CSS today.
5 of these tones could not hold the source chroma of 0.233 and were
reduced, which is why the chroma column falls away at both ends. sRGB
simply has less room for saturated colour near white and near black.
Reducing chroma keeps the hue; clipping the channels instead, which is
what a naive conversion does, shifts it, and a bright blue clipped at a
dark tone comes back violet.
The contrast figures are against white and black, whichever is better,
so you can see where the palette crosses 4.5:1 for body text and 3:1 for
large text and UI. In a tonal palette that crossing point is roughly
tone 50 for white text and tone 60 for black, which is the property that
makes tonal palettes useful for theming.
Output is valid and updates as you type.
Fix the highlighted fields to update the output.
Material 2’s published palettes, the red 500s and the blue 700s everybody has used, were hand-picked by designers. No formula reproduces them, and any tool claiming to generate “the Material palette” for your colour is generating something that looks like them.
Material 3 changed that. Its palettes are tonal: hold the hue and the chroma, step the tone from 0 to 100. That is an algorithm, and it can be reproduced, which is what this does. The steps are labelled with both the Material 3 tone numbers and the familiar 50 to 900 names.
How to use
- Put in your colour. On the 50 to 900 scale it becomes the 500 step, at its own tone.
- Turn on the Material 3 scale if you want tones 0 to 100 instead.
- Lower the chroma for a calmer palette.
- Copy the hex values or the custom property block.
Example
#1e56ec on the 50 to 900 scale:
Source #1e56ec · oklch(52.1% 0.233 264.0)
Scale Material 2 names, 50 to 900
Chroma 100% of the source
50 #e6efff tone 95 chroma 0.025 black text 18.16:1
100 #cedeff tone 90 chroma 0.049 black text 15.52:1
200 #9dbdff tone 80 chroma 0.101 black text 11.16:1
300 #6c9aff tone 70 chroma 0.157 black text 7.70:1
400 #3a73ff tone 60 chroma 0.217 black text 5.08:1
500 * #1e56ec tone 52 chroma 0.233 white text 5.84:1
600 #0a3dd3 tone 45 chroma 0.233 white text 8.01:1
700 #0029c2 tone 40 chroma 0.233 white text 10.02:1
800 #000094 tone 30 chroma 0.209 white text 14.71:1
900 #000054 tone 20 chroma 0.141 white text 18.62:1
Two things to read off that. The 500 step is exactly the colour you gave, so the palette is built around it rather than near it. And the chroma column falls away at both ends, because sRGB has less room for saturated colour close to white and close to black: 0.233 is simply not available at tone 95.
The text column is where the palette becomes useful for theming. Somewhere around tone 50 the better text colour flips from black to white, and that crossing point is the same for every hue in a tonal palette, which is what lets one set of rules theme a whole interface.
Pitfalls
This will not match Google’s own output digit for digit. Material 3’s tone is HCT lightness and this uses OKLCH. Both are perceptual spaces built on the same idea and the tones land within a couple of points of each other. OKLCH is the one you can write in CSS today; HCT is not in any browser.
It will not match Material 2’s palettes at all. Those were chosen by eye. If you need the official red 500, look it up rather than generating it.
Out-of-gamut tones lose chroma, not hue. When a tone cannot hold the source chroma, this reduces the chroma until it fits. The naive alternative, clipping the red, green and blue channels, shifts the hue: a bright blue clipped at a dark tone comes back violet. That is why generated dark shades in some tools look like a different colour.
A tonal palette is not a colour scheme. Material 3 builds a scheme from several tonal palettes: primary, secondary, tertiary, neutral, and a neutral variant, and then assigns roles to specific tones. One palette is the raw material for that, not the finished thing.
Ten steps is more than most interfaces need. Three or four, chosen for their contrast behaviour, will carry a design further than ten that are all nearly usable. The UI colour palette generator on this site works the other way round: it starts from the roles and fits the contrast.
Contrast is against black and white here. A step used as a background behind a mid grey, or as text on a tinted surface, has a different ratio, and the contrast checker on this site is the tool for that case.
Compatibility
Arithmetic in the browser: nothing is uploaded and nothing is stored. The share link carries the colour.
Conversion runs through OKLCH: the source colour is converted to OKLCH, the lightness is replaced with each tone, and the result is converted back to sRGB with chroma reduced until it fits. Contrast ratios use the WCAG 2 relative luminance formula, which is what conformance is measured against.
Output is hex, which means sRGB. oklch() is in every current browser since 2023, so if
you want the palette in a wider gamut you can write the tones as oklch() directly and
let the browser use whatever the display can show; the hex values here are the sRGB
fallback for that.
The custom property block is plain CSS with a prefix you choose, so it drops into a
theme, a theme.json, a Tailwind config or a design token file.
Frequently asked questions
Which scale should I use, 50 to 900 or 0 to 100?
Why is my 500 not at tone 50?
#1e56ec is tone
52. Forcing it to exactly 50 would change the colour you asked for, which is the wrong
trade.How do I get a full Material 3 scheme?
What does chroma at 60 percent do?
Is OKLCH better than HSL for this?
hsl(60 100% 50%) and
hsl(240 100% 50%) are the same lightness number and one is yellow while the other is
nearly black. In OKLCH the number means what it says across hues, which is the whole
point of a tonal scale.