--- system: material category: foundations topic: colors content_type: guidance status: latest version_label: "M3 / Material You" retrieved: 2026-05-11 source_url: https://m3.material.io/styles/color/system/overview tags: [color, tokens, dynamic-color, tonal-palettes, theming, dark-mode, accessibility, hct] --- # Material Design 3 — Color System ## Philosophy Color in M3 serves two simultaneous masters: **brand identity** and **user personalization**. The system is built around the premise that a user's chosen wallpaper or a single brand seed color should be able to drive the entire UI color scheme algorithmically — not just accent colors, but every surface, container, text, and icon across both light and dark themes. This philosophy required a new color science foundation. M3 uses the **HCT color space** (Hue, Chroma, Tone) rather than traditional HSL or RGB. HCT is perceptually accurate: its tone value corresponds to human-perceived lightness, which means that color contrast and accessibility can be predicted reliably across any hue combination. This is what makes it possible to generate accessible color schemes algorithmically — WCAG AA contrast is preserved by the math, not enforced manually. The practical outcome for designers: you define a small set of **key colors** (typically 4–6), and M3's tools generate a complete, accessible, light+dark color scheme automatically. --- ## Token Architecture: Three Tiers M3's color token architecture has three distinct layers. Understanding the relationship between them is essential to using or replicating the system. ### Tier 1 — Reference Tokens (`md-ref-palette`) Reference tokens hold the raw color palette — the complete tonal range for each key color. Each key color generates a **tonal palette** of 13 tones from 0 (black) to 100 (white), with meaningful stops at 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, and 99. Reference tokens carry no semantic meaning. They are the color universe from which system tokens draw. On the web, reference palette tokens (`--md-ref-palette-*`) are not directly supported in the Material Web library — they exist at the specification level and in tooling outputs. ### Tier 2 — System Tokens (`md-sys-color`) System tokens assign **semantic roles** to tones from the reference palettes. A system token says "this UI role uses this tone of this palette" — for example, `primary` maps to tone 40 of the primary palette in light theme, and tone 80 in dark theme. System tokens are the primary customization interface. Changing a key color updates the reference palette, which cascades to all system tokens. System tokens are what you set in CSS (`--md-sys-color-primary`, etc.) to theme your application. ### Tier 3 — Component Tokens (`md-comp-*`) Component tokens map specific component elements to system tokens. A filled button's container color points to `primary`; its label color points to `on-primary`. Component tokens are rarely set directly; they exist to make each component's color logic explicit and overridable. **The key insight:** because components reference system tokens, not reference tokens, when Dynamic Color generates a new reference palette from a user's wallpaper, the entire application updates automatically and consistently without any component-level changes. --- ## Key Colors and Their Roles M3 defines five key colors from which the full scheme is derived: **Primary** — The most prominent color in the UI. Used for key components: filled buttons, FABs, active navigation indicators. Tone 40 in light, tone 80 in dark. **Secondary** — A supporting accent for less prominent components: chips, certain list items. Typically a more muted variation of the primary hue. **Tertiary** — A contrasting accent for differentiation and emphasis. Intentionally distinct from primary and secondary to break visual monotony. Good for highlighted items, badges. **Error** — Reserved exclusively for error states, destructive actions, validation failures. **Neutral** — Generates the surface, background, and outline colors. Drives the UI's underlying canvas. --- ## Color Roles (System Token Layer) From these five palettes, M3 defines a structured set of color roles. Each role has a **container** variant for backgrounds and a corresponding **on-** variant for content placed on top of it — ensuring contrast is always paired. ### Primary Group - `primary` — Key interactive elements; filled button containers, FAB backgrounds, active tab indicators - `on-primary` — Content on primary: button labels, FAB icons - `primary-container` — Less prominent uses of primary hue; tonal buttons, selected chip backgrounds - `on-primary-container` — Content on primary-container - `primary-fixed` / `primary-fixed-dim` — Fixed versions not affected by Dynamic Color (for consistent cross-scheme elements) ### Secondary Group - `secondary`, `on-secondary`, `secondary-container`, `on-secondary-container` - Parallel structure to primary; used for secondary actions, filter chips, certain badges ### Tertiary Group - `tertiary`, `on-tertiary`, `tertiary-container`, `on-tertiary-container` - Contrasting accent; used sparingly to break monotony and draw attention to specific elements ### Error Group - `error`, `on-error`, `error-container`, `on-error-container` - Never repurposed for anything other than error/destructive states ### Surface and Background Surfaces are the most nuanced part of the M3 color system. Rather than a single surface color, M3 defines a family of surface tones for layering: - `background` — Page-level background - `on-background` — Content on background - `surface` — Default surface for cards, sheets, dialogs - `on-surface` — Primary content on surface - `surface-variant` — Alternate surface for lower-emphasis containers - `on-surface-variant` — Secondary content on surfaces - `surface-bright` — Highest surface tone; top sheets, certain overlays - `surface-dim` — Lowest surface tone; recessed areas - `surface-container-lowest` / `surface-container-low` / `surface-container` / `surface-container-high` / `surface-container-highest` — A five-step surface container scale for layering UI depth without shadows ### Outline - `outline` — Borders and dividers that need sufficient contrast - `outline-variant` — Decorative borders with lower contrast (decorative separators, card outlines when low emphasis is appropriate) ### Inverse and Fixed - `inverse-surface` — For elements like snackbars that appear on inverted backgrounds - `inverse-on-surface` — Content on inverse-surface - `inverse-primary` — For tonal buttons on inverse surfaces - `scrim` — Darkened overlay behind modal sheets and dialogs --- ## Dynamic Color Dynamic Color is the M3 feature that makes user-personalized theming possible. On Android 12+, the system extracts a seed color from the user's wallpaper and runs it through the HCT color generation algorithm, producing a full set of tonal palettes. These palettes are then mapped to the system token layer automatically. For products that cannot or should not use Dynamic Color (web, non-Android platforms, strict brand requirements), a static baseline scheme is used. The Material Theme Builder tool generates static light and dark CSS/Kotlin/Dart themes from any seed color. **Design principle:** Do not design with specific hex values as your reference. Design with token roles. If your component says "use `primary`," it will be correct regardless of what color `primary` resolves to — whether that's your brand blue, a user's wallpaper-derived purple, or the M3 baseline teal. --- ## Light and Dark Themes M3 provides a complete dual-theme model out of the box. Each system color token has different tone assignments for light and dark: - In **light theme**, primary uses tone 40 (darker, higher contrast against light surfaces) - In **dark theme**, primary uses tone 80 (lighter, sufficient contrast against dark surfaces) This means a single set of token names (`primary`, `surface`, etc.) works for both themes — the theme context determines which tonal value is resolved. You never need separate token sets for light and dark; you need separate theme bindings. --- ## Accessibility The tonal palette system is designed to produce accessible contrast by default: - `on-*` colors are calculated to meet WCAG AA contrast against their paired `*` colors - The five-step surface container scale provides predictable layering depth without relying on arbitrary contrast decisions - `surface-variant` + `on-surface-variant` are designed specifically for secondary text and icons at reduced prominence while remaining readable When customizing beyond the auto-generated scheme, always verify contrast ratios between `on-*` and `*` token pairs. The Material Theme Builder lint tool validates WCAG AA automatically. --- ## Do's and Don'ts **Do:** - Use token roles, not raw hex values, in component implementations - Pair every `*` container color with its `on-*` counterpart for text/icons - Use `surface-container-*` variants for layering rather than opacity hacks - Generate your color scheme from a single seed color using Material Theme Builder - Always provide both light and dark theme token sets **Don't:** - Use `error` for anything other than errors and destructive actions - Mix tones from different palettes without testing contrast — the system's safety guarantees only apply within the designed pairings - Hardcode hex values in component styles — this breaks Dynamic Color and theme switching - Use more than three accent colors (primary, secondary, tertiary) — additional custom colors require careful contrast verification outside the system's safety guarantees