Tailwind Material Colors

A TailwindCSS plugin to use the Material Design 3 Color System with Tailwind, with Dynamic Color support.

Key features

Installation & Usage

npm install --save-dev tailwind-material-colors
tailwind.config.js
const { withMaterialColors } = require('tailwind-material-colors');

const config = {
// Here, your tailwind config.
};

module.exports = withMaterialColors(config, {
// Here, your base colors as HEX values
// primary is required
// secondary and/or tertiary are optional, if not set they will be derived from the primary color
primary: '#ff0000',
secondary: '#ffff00',
tertiary: '#0000ff',
// extra named colors may also be included
green: '#00ff00'
blue: '#0000ff'
});

The colors you supply will be transformed by M3. In the example configuration above, where the provided primary base color is pure red (#ff0000), the resulting primary colors are #c00100 and #ffb4a8 for light and dark mode respectively. This is an intentional effect of the M3 algorithm in the interest of good contrast ratios and pleasing aesthetics.

If you don't want a color to be harmonized to the primary color, pass { hex: "#xxxxxx", harmonize: false } as the value instead of the plain hex color.

What do I get?

1. A Tailwind color palette

The plugin will generate a color palette. Most of the colors on it have an on-color counterpart. on-X is the default color of content inside an element with background color X.

For example, an element with a primary-container background will have on-primary-container content.

When you use the .bg-primary-container class, the default text color will be set to on-primary-container.

Default content (on-primary-container)
Content with .text-outline class
.bg-primary-container

Default content color will not be set when using opacity modifiers (such as bg-primary/50). You can specify text color or use bg-primary bg-opacity-50 instead.

Color palette
primary
on-primary
primary-container
on-primary-container
secondary
on-secondary
secondary-container
on-secondary-container
tertiary
on-tertiary
tertiary-container
on-tertiary-container
error
on-error
error-container
on-error-container
background
on-background
surface
on-surface
surface-variant
on-surface-variant
inverse-surface
on-inverse-surface
outline
inverse-primary
black
white
transparent
current

The generated colors can be used with any of Tailwind's usual utilities (such as bg-, text-, border-, fill-, stroke-, or shadow-).

2. Automatic dark mode

All the generated colors will automatically switch to their dark mode shades based on your defined Dark Mode Strategy, be it CSS prefers-color-scheme or a custom class. There's no need to use the dark: variant.

You can try it right here:

3. Interaction states

This plugin provides easy to use interaction states that follow the M3 guidelines on that topic. For every color with an on-color counterpart, an interactive-bg- utility will be generated.

Interactive elements use the concept of state layers: on hover or focus, the background color is overlayed with the on-color at certain amount of opacity (8% on hover, 12% on press and focus, and 16% on drag).

primary-container background
on-primary-container state layer with variable opacity
on-primary-container content
Content

This is achieved without CSS pseudoelements by directly changing the background color to the expected result.

All interactive colors
Primary
.interactive-bg-primary
Primary Container
.interactive-bg-primary-container
Secondary
.interactive-bg-secondary
Secondary Container
.interactive-bg-secondary-container
Tertiary
.interactive-bg-tertiary
Tertiary Container
.interactive-bg-tertiary-container
Error
.interactive-bg-error
Error Container
.interactive-bg-error-container
Background
.interactive-bg-background
Surface
.interactive-bg-surface
Surface Variant
.interactive-bg-surface-variant
Inverse Surface
.interactive-bg-inverse-surface

For drag states, use JavaScript to apply the dragged-bg-primary class instead of interactive-bg-primary while the element is being dragged.

Plugin configuration

Extending the Tailwind color palette

The plugin will add colors to the theme.colors key of your Tailwind config. Any custom colors already defined there will remain if there are no name conflicts, but as per the Tailwind docs, this disables the default Tailwind color palette. If you wish to keep it, add { extend: true } as a third argument to the withMaterialColors call.

module.exports = withMaterialColors(config, colors, { extend: true });

Dynamic Color

You can update the generated theme at runtime, directly on client-side JavaScript, with the updateTheme function.

example.js
import { updateTheme } from "tailwind-material-colors/lib/updateTheme.esm";

const makeThemeRed = () => {
updateTheme({
// set a new primary color (and optionally any other colors in your theme)
primary: '#ff0000',
green: '#00ff00'
},
// second argument is your chosen dark mode strategy (usually 'media' or 'class')
'media'
);

It's recommended to set all colors when changing primary because the harmonize feature (on by default) will affect the resulting shades.

updateTheme can't create new colors, only update existing ones.

⚠️ The updateTheme function is around 75KB. If possible, load it asynchronously to reduce load times.

Try dynamic color