Material Design Color System: How Google's Palette Works

Color Code6 min read

The Material Design color palette with its shade families
Nineteen families, ten shades each, plus accent tones.

Long before design tokens were fashionable, Google shipped a color system so tidy it ended up inside almost every app framework: nineteen color families, each with ten numbered shades and up to four accents. The Material Design palette is still the default in many themes today — and its numbering is the easiest part to get wrong.

Nineteen families, one shared ramp

The 2014 palette starts from a hue, such as Blue, and gives it the same shade structure as every other hue:

  • 10 shades numbered 50, 100, 200, 300, 400, 500, 600, 700, 800, 900 — lightest to darkest. 50 is close to white, 900 is nearly black.
  • 4 accent shades prefixed with A: A100, A200, A400, A700 — brighter, more saturated variants for highlights.

Every family follows that pattern except three neutrals — Brown, Grey and Blue Grey — which ship only the ten shades and no accents. That is why the numbering jumps from 900 to A100 for most hues but stops at 900 for the neutrals.

Anatomy of a family

Here is the full Blue family, exactly as it appears in the Material spec and in the color charts:

ShadeHexShadeHex
50#E3F2FD600#1E88E5
100#BBDEFB700#1976D2
200#90CAF9800#1565C0
300#64B5F6900#0D47A1
400#42A5F5A100#82B1FF
500#2196F3A200#448AFF
——A400#2979FF
——A700#2962FF

Two reference points worth remembering: Red 500 is #F44336, and the classic accent example in Google's own documentation is Purple A200 — #E040FB. In the newer OKLCH model, Blue 500 lands at oklch(65.8% 0.169 248.8), which is a useful way to see how light the "primary" shade of a hue actually is.

Which shade is for what

The spec assigns roles rather than leaving you to guess:

  • 500 is the primary color — the shade you build buttons, app bars and links from. blue[500] is the literal Material primary blue.
  • 700 is the dark variant of that primary, used for hover and pressed states, and for text that has to read as the same hue but stronger.
  • A200 is the default accent for floating action buttons and highlights, with A400 as the alternate, more saturated accent.
  • 50–100 are for backgrounds and section fills, 200–300 for borders and dividers, and 800–900 for dark surfaces in light themes.

Material's dark theme guidance flipped the top of the ramp: instead of the vivid 500, dark themes use desaturated variants around the 200 tone on a #121212 surface, so the color reads as a tint rather than a glare.

Contrast: the part everyone gets wrong

The palette looks evenly spaced, but equal shade numbers do not mean equal readability. Two examples, measured against white:

ColorText on itContrast ratioVerdict
Yellow 500 #FFEB3BBlack~17.2:1Excellent
Yellow 500 #FFEB3BWhite~1.2:1Unusable
Blue 500 #2196F3White~3.1:1Large text only

That second and third row explain why Material buttons can use white text on a mid blue, but body copy cannot: white-on-Blue-500 passes WCAG AA only as large text — 18pt, or 14pt bold, which is exactly how Material styles button labels. Push the same pairing onto 12–14px regular text and it fails. Frameworks like MUI sidestep the problem by computing a contrastText per shade instead of hardcoding white.

The lesson generalizes beyond Material: never trust a shade number for accessibility. Check the actual pair with the contrast checker, and if a brand color has to carry text, walk the ramp outward — 700 or 800 — until the ratio passes.

From fixed palette to generated theme: Material 3

In 2021 Google replaced the hand-picked swatches with a system that generates them. Material Design 3 (Material You) keeps five key color groups — primary, secondary, tertiary, neutral and neutral-variant — and derives everything else from a single seed color.

The mechanism is a tonal palette: each group is expanded into a ramp of fixed tones from 0 (black) to 100 (white) — steps such as 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99 and 100 — computed in HCT, Google's perceptual color space (hue, chroma, tone). Two properties follow from that:

  • Tone tracks perceived lightness, so a palette generated from any seed color has even steps, in the same way OKLCH fixes HSL's uneven lightness.
  • Roles are named, not numbered. Instead of "use Blue 500", a Material 3 theme defines primary, on-primary, primary-container, on-primary-container, secondary, tertiary, surface, surface-variant, outline and error, and maps each role to a tone from a tonal palette. Dark mode is a second mapping of the same palettes, not a second palette.

The visible payoff is dynamic color: on Android 12 and later, the operating system can hand an app a scheme generated from the user's wallpaper, and a harmonization step nudges your brand colors toward it so custom colors do not clash. Google's Material Theme Builder exports the result as tokens for Figma, Android and the web.

Material vs Tailwind vs web-safe

The three systems in the color charts solve the same problem with different conventions:

SystemSteps per hueAccentsModel
Material 2 (2014)50–900 (10)A100–A700, on 16 of 19 huesHand-picked swatches
Material 3 (2021)Tones 0–100Roles, not shadesGenerated from a seed color in HCT
Tailwind50–950 (11)NoneTuned sRGB ramps, OKLCH in v4
Web-safe6 per channelNone1990s 8-bit display cube

If you are weighing the numbered ramps against each other, the Tailwind scale guide covers the 50–950 convention, and the web-safe palette post explains why its 216 colors are history.

Using the palette without inheriting its mistakes

  • Start from a role, not a swatch. Decide "primary button", "muted border", "dark surface" first, then pick shades — that is how the M3 role names are organized, and it keeps themes consistent.
  • Do not mix accent and shade numbering. A200 is not "twice as dark as 100"; accents are a separate axis of saturation.
  • Build your own ramp from your brand color instead of forcing it into someone else's hue. The Tailwind color generator produces a 50–950 scale, and the shades generator gives you a quicker tint/shade ramp to compare against Material's steps.
  • Verify contrast per pair. Material's own example colors include both the best (black on Yellow 500) and worst (white on Yellow 500) cases in the same family.
Try it: open the Material tab in the color charts, grab Blue 500 (#2196F3) and Red 500 (#F44336), and check both against white and black in the contrast checker. Then compare Blue 500 with Blue 700 — the two-step move Material expects you to make when a hue has to carry text.

Material's real contribution was not the swatches but the discipline around them: a fixed ramp per hue, one shade per role, and an explicit contrast rule. Whether you use the 2014 palette, a Material 3 tonal theme or your own tokens, that structure is what makes a color system survive past the first redesign.

material designpaletteshadecolor charts

Tools for this guide

Related posts