Color
Materialize offers a lot of colors which can be used in your next project.
Material color roles
Use Material roles when colors should follow the theme. A source color generates a coordinated palette; CSS variables carry that palette to your page and components. The named colors below, such as teal lighten-2, are fixed colors and do not automatically follow the generated palette.
| Use | Background | Matching text |
|---|---|---|
| Main action | primary | on-primary |
| Soft accent panel | primary-container | on-primary-container |
| Page or card | surface | on-surface |
| Secondary surface | surface-variant | on-surface-variant |
| Error message | error-container | on-error-container |
Use background classes and their matching -text classes together. An on-* role is the foreground intended for that background.
<!-- Theme-aware colors, inherited from the nearest theme scope. -->
<div class="card-panel primary-container on-primary-container-text">
A soft accent panel with its matching text color.
</div>
<button type="button" class="btn filled">Primary action</button>/* The same roles work in your own CSS. */
.my-panel {
background: var(--md-sys-color-surface);
color: var(--md-sys-color-on-surface);
border: 1px solid var(--md-sys-color-outline-variant);
}Generate a palette
Install @material/material-color-utilities (already included in these docs). These examples use the package’s TypeScript theme helpers.
// npm install @material/material-color-utilities
import { argbFromHex, themeFromSourceColor, applyTheme } from '@material/material-color-utilities';
// 1. Convert a source hex color to the library's ARGB representation.
// 2. Generate coordinated light and dark schemes.
const theme = themeFromSourceColor(argbFromHex('#6750A4'));
// 3. Write --md-sys-color-* CSS variables onto the target.
applyTheme(theme, { target: document.body, dark: false });The source color is a seed, so the generated primary color may differ from the exact hex you provided. applyTheme writes variables; elements must use those variables or Material color classes to show the result.
Try page, card, and section themes
Use the color picker to choose a source color, press Save, then choose a mode and target. Try different colors for the card and section to compare them with the page. A locally themed element keeps its palette until you apply a new one or reset it.
Choose a color and target. Previews do not change saved preferences.
Card theme
This card can have its own palette and mode.
Section theme
One wrapper passes its palette to all descendants.
Change the whole page
const theme = themeFromSourceColor(argbFromHex('#006B5F'));
function setPageMode(dark: boolean) {
applyTheme(theme, { target: document.body, dark });
// Keep Materialize mode selectors and native form controls in sync.
document.documentElement.setAttribute('theme', dark ? 'dark' : 'light');
document.documentElement.style.colorScheme = dark ? 'dark' : 'light';
}
setPageMode(window.matchMedia('(prefers-color-scheme: dark)').matches);
// Call setPageMode(true) or setPageMode(false) from your own theme toggle.Use document.body consistently when that is where your application writes its palette. Variables on body override inherited values from html. Changing only the theme attribute does not regenerate variables written by applyTheme; reapply the matching scheme too.
For this documentation project, its Themes helper also saves the source color and mode in local storage:
// This helper belongs to the documentation project; it is not a library export.
import { Themes } from './themes';
const themes = new Themes(document);
themes.setThemePrimaryColor('#006B5F');
themes.setDarkMode();
// themes.setLightMode();Theme a card or another element
<!-- The palette is local to this element and its descendants. -->
<div id="project-card" class="card-panel surface on-surface-text">
<h5>Project card</h5>
<button type="button" class="btn filled">Open project</button>
</div>const card = document.querySelector<HTMLElement>('#project-card')!;
const cardTheme = themeFromSourceColor(argbFromHex('#B15C00'));
applyTheme(cardTheme, { target: card, dark: false });
card.style.colorScheme = 'light';
// Use the same approach for a section, toolbar, dialog, or button.
// Applying to a wrapper also themes the children inside it.
// A button can be targeted directly with applyTheme(theme, { target: button, dark: false }).CSS variables inherit downward, so a local palette does not affect siblings or parents. To follow page mode, reapply each local palette with the new dark value when your theme toggle changes.
A dropdown or tooltip appended to document.body inherits the page palette. To match a themed card, render it inside that scope where the component supports it, or apply the card palette to the popup itself.
// Return a locally themed element to the inherited page palette.
for (const property of Array.from(card.style)) {
if (property.startsWith('--md-sys-color-')) card.style.removeProperty(property);
}
card.style.removeProperty('color-scheme');Change only one element color
If you only need a different accent on one component, use another role such as secondary-container, or override a matching token pair locally. A token override does not generate a full palette or a separate dark scheme.
<div class="card-panel secondary-container on-secondary-container-text">
Uses the existing secondary container colors.
</div>
<button type="button" class="btn filled"
style="--md-sys-color-primary: #285943; --md-sys-color-on-primary: #ffffff;">
Local green action
</button>Prefer generated schemes for light/dark support. If you choose custom pairs, verify their text contrast in every state. Setting --md-sys-color-primary alone does not update on-primary, container colors, or the rest of the palette.
Live preview TypeScript
import {
applyTheme,
argbFromHex,
themeFromSourceColor,
} from "@material/material-color-utilities";
import { Themes } from "./themes";
import "./color-theme-demo.scss";
const seed = document.querySelector<HTMLInputElement>("#theme-demo-seed")!;
const dark = document.querySelector<HTMLInputElement>("#theme-demo-dark")!;
const card = document.querySelector<HTMLElement>("#theme-demo-card")!;
const section = document.querySelector<HTMLElement>("#theme-demo-section")!;
const status = document.querySelector<HTMLElement>("#theme-demo-status")!;
const savedTheme = new Themes(document);
dark.checked = savedTheme.isDarkMode();
// Only CSS tokens on the chosen target change; no saved preference is overwritten.
function previewTheme(target: HTMLElement) {
const theme = themeFromSourceColor(argbFromHex(seed.value));
applyTheme(theme, { target, dark: dark.checked });
target.style.colorScheme = dark.checked ? "dark" : "light";
if (target === document.body) {
document.documentElement.setAttribute(
"theme",
dark.checked ? "dark" : "light",
);
document.documentElement.style.colorScheme = dark.checked
? "dark"
: "light";
}
}
document
.querySelector("#theme-demo-page-apply")!
.addEventListener("click", () => {
previewTheme(document.body);
status.textContent = `Page preview: ${seed.value}, ${dark.checked ? "dark" : "light"} mode.`;
});
for (const [id, target] of [
["#theme-demo-card-apply", card],
["#theme-demo-section-apply", section],
] as const) {
document.querySelector(id)!.addEventListener("click", () => {
previewTheme(target);
status.textContent = `${target === card ? "Card" : "Section"} preview updated; the page palette is unchanged.`;
});
}
document.querySelector("#theme-demo-reset")!.addEventListener("click", () => {
// Remove only generated theme properties, so these examples inherit the page again.
for (const target of [card, section]) {
Array.from(target.style)
.filter((name) => name.startsWith("--md-sys-color-"))
.forEach((name) => target.style.removeProperty(name));
target.style.removeProperty("color-scheme");
}
const isDark = savedTheme.isDarkMode();
savedTheme.applyThemeProperties(isDark);
document.body.style.removeProperty("color-scheme");
document.documentElement.setAttribute("theme", isDark ? "dark" : "light");
dark.checked = isDark;
status.textContent =
"Saved page theme restored. Card and section inherit it again.";
});Live preview SCSS
.color-theme-controls {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 12px;
margin-block: 16px;
}
.color-theme-controls > label {
display: inline-flex;
align-items: center;
gap: 8px;
color: var(--md-sys-color-on-surface);
}
.color-theme-controls input[type="color"] {
width: 48px;
height: 40px;
padding: 4px;
border: 1px solid var(--md-sys-color-outline-variant);
border-radius: 8px;
}
.color-theme-surface {
padding: 24px;
margin-block: 16px;
border-radius: 16px;
border: 1px solid var(--md-sys-color-outline-variant);
background: var(--md-sys-color-surface);
color: var(--md-sys-color-on-surface);
}
.color-theme-surface h5 {
margin-top: 0;
}
.color-theme-note {
padding: 12px 16px;
border-radius: 12px;
background: var(--md-sys-color-primary-container);
color: var(--md-sys-color-on-primary-container);
margin-block: 16px;
}Fixed color classes
Here is a color palette based on the material design base colors. Each of these colors is defined with a base color class and an optional lighten or darken class.
Background Color
To apply a background color, just add the color name and light/darkness as a class to the element.
<div class="card-panel teal lighten-2">This is a card panel with a teal lighten-2 class</div>Text Color
To apply a text color, just append
-text to the color class like this:
<div class="card-panel">
<span class="blue-text text-darken-2">This is a card panel with dark blue text</span>
</div>Sass
For background colors, you can apply the color simply by extending the classes like the example below.
.ilike-blue-container {
@extend .blue, .lighten-4;
}
For changing text color, you can apply the color simply by extending the classes like the example below.
.ilike-blue-container {
@extend .blue-text, .text-lighten-4;
}
Color Palette
Borders
Every color also has a -border variant, applying it to border-color instead of
background-color. Combine it with a shade class exactly like the background/text variants
(teal-border darken-2).
<div class="card-panel teal-border darken-2" style="border: 3px solid;">teal-border darken-2</div>
<div class="card-panel red-border accent-3" style="border: 3px solid;">red-border accent-3</div>
<div class="card-panel amber-border" style="border: 3px solid;">amber-border</div>Light/Dark Mode Colors
light-mode-* and dark-mode-* variants apply a color only while the system is actually in that
color scheme (via @media (prefers-color-scheme: ...)) - the other one does nothing. Put both on the same element to pick a
different color per scheme automatically, without any JS:
<div class="card-panel light-mode-indigo dark-mode-amber lighten-2-light-mode darken-2-dark-mode">
Indigo lighten-2 in light mode, amber darken-2 in dark mode
</div>The base color (no shade) is simpler - no extra suffix needed:
<div class="card-panel light-mode-red dark-mode-blue">
Plain red in light mode, plain blue in dark mode
</div>Text and border follow the same pattern: light-mode-*-text/dark-mode-*-text and light-mode-*-border/dark-mode-*-border.
Gradients
30 ready-made two-color gradients, each named gradient-45deg-<start>-<end>. Add
gradient-shadow alongside one for a drop shadow tinted to match the gradient's end color (like the two below).
<div class="gradient-45deg-purple-pink" style="height: 80px;"></div>
<div class="gradient-45deg-orange-deep-orange gradient-shadow" style="height: 80px;"></div>light-blue-teal + shadow
indigo-light-blue + shadow
light-blue-indigo + shadow
yellow-green + shadow
orange-deep-orange + shadow
deep-purple-purple + shadow
red-pink + shadow
light-green-amber + shadow
amber-amber + shadow
purple-pink + shadow
teal-cyan + shadow
blue-grey-blue-grey + shadow
orange-amber + shadow
indigo-blue + shadow
brown-brown + shadow
blue-grey-blue + shadow
purple-deep-orange + shadow
green-teal + shadow
purple-light-blue + shadow
cyan-cyan + shadow
yellow-teal + shadow
purple-deep-purple + shadow
cyan-light-green + shadow
purple-amber + shadow
indigo-purple + shadow
deep-purple-blue + shadow
deep-orange-orange + shadow
light-blue-cyan + shadow
blue-indigo + shadow
semi-dark + shadow