Material 3 Expressive for the web
Material Design.
More expressive.
Color that feels personal, shapes that respond, and motion that feels natural, in an independent collection of web components.
Try it
Make it yours
Pick a seed color. Every color role on this page is generated from it.
What makes it expressive
Color with character
Start with one seed color. Material Color Utilities turn it into a complete scheme for surfaces, controls, light and dark themes, and contrast levels.
Shapes that respond
Buttons, chips, and toggles change shape as they are pressed or selected. The 35 shapes of the Material shape library are ready to use.
Motion with meaning
Springs drive movement and color. Spatial springs may overshoot a little, and effects springs settle without a bounce.
Start building
Install the package, or add two lines to any HTML page.
npm i @materialwebunofficial/md3e-web
Get started
Add the design tokens and the components to any page. The library is plain JavaScript with no runtime dependencies, so it works with or without a framework.
Install
Package manager
For apps built with a bundler such as Vite or webpack.
npm install @materialwebunofficial/md3e-web
pnpm add @materialwebunofficial/md3e-web
bun add @materialwebunofficial/md3e-web
CDN
For a single HTML page, with no build step.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@materialwebunofficial/md3e-web/dist/tokens.min.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@materialwebunofficial/md3e-web/dist/md3-expressive.esm.js"></script>
Your first page
Save this as index.html and open it in a browser.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@materialwebunofficial/md3e-web/dist/tokens.min.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@materialwebunofficial/md3e-web/dist/md3-expressive.esm.js"></script>
</head>
<body style="background: var(--md-sys-color-surface); color: var(--md-sys-color-on-surface)">
<h1 class="md-headline-medium">Hello, Material</h1>
<md-button variant="filled" icon="favorite" label="Like"></md-button>
<md-progress-indicator type="linear" variant="wavy" value="70"></md-progress-indicator>
</body>
</html>
Frameworks
The components are custom elements, so frameworks render them like any other HTML element.
'use client';
import { useEffect } from 'react';
import '@materialwebunofficial/md3e-web/tokens.css';
export default function Confirm() {
useEffect(() => { import('@materialwebunofficial/md3e-web'); }, []);
return <md-button variant="filled" icon="check" label="Confirm"></md-button>;
}
// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue({
template: { compilerOptions: { isCustomElement: tag => tag.startsWith('md-') } }
})]
});
<script>
import '@materialwebunofficial/md3e-web/tokens.css';
import '@materialwebunofficial/md3e-web';
let volume = $state(65);
</script>
<md-slider value={volume} oninput={e => volume = e.detail.value}></md-slider>
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@materialwebunofficial/md3e-web';
@Component({
selector: 'app-root',
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `<md-button variant="filled" label="Save"></md-button>`
})
export class AppComponent {}
import '@materialwebunofficial/md3e-web';
const button = document.createElement('md-button');
button.setAttribute('label', 'Save');
button.addEventListener('click', () => console.log('saved'));
document.body.append(button);
Theming
A theme element generates the color scheme from a seed color. The expressive theme also selects the expressive motion scheme.
<md-expressive-theme global primary-seed="#00639B" color-mode="auto" palette-variant="tonal-spot">
<!-- Your app -->
</md-expressive-theme>
Or apply a scheme from JavaScript:
import { applyDynamicTheme } from '@materialwebunofficial/md3e-web';
// Tonal spot, the default dynamic color variant, for the dark theme.
applyDynamicTheme('#00639B', true);
// Any other Material variant, such as vibrant or monochrome.
applyDynamicTheme('#00639B', true, 'vibrant');
Design tokens
Components read the system tokens below. Use them in your own styles to stay consistent.
| Token | Value | Used for |
|---|---|---|
--md-sys-color-primary | Dynamic color role | Filled buttons, active states |
--md-sys-color-surface-container | Dynamic color role | Menus, navigation surfaces |
--md-sys-shape-corner-extra-large | 28px | Dialogs, sheets, large containers |
--md-sys-shape-corner-full | Fully rounded | Buttons, chips, indicators |
--md-sys-typescale-display-large | 57/64, weight 400 | Large, short headlines |
--md-sys-typescale-headline-medium-emphasized | 28/36, weight 500 | Emphasized headings |
--md-sys-typescale-title-medium-emphasized | 16/24, weight 700 | Emphasized titles |
--md-sys-typescale-body-large | 16/24, weight 400 | Long-form text |
--md-sys-motion-easing-expressive-spatial | Spring curve | Movement that may overshoot |
Components
Components are interactive building blocks for creating a user interface. They are organized by purpose: actions, communication, containment, navigation, selection, and text input.
Actions
Buttons, FABs, and their variations help people take action and make choices.
Buttons
Buttons prompt most actions in a UI. They come in five sizes, and their shape responds to press and selection.
<md-button variant="filled" label="Button" icon="add"></md-button>
<md-button size="m" variant="filled" label="Button"></md-button>
Button groups
Button groups organize buttons and add interactions between them. Standard groups react to presses; connected groups replace segmented buttons for selection.
<md-button-group><md-button variant="tonal" icon="skip_previous" aria-label="Previous"></md-button><md-button variant="filled" icon="play_arrow" label="Play"></md-button>...</md-button-group>
<md-button-group variant="connected" selection="single"><md-button icon="work" label="Work" selected></md-button>...</md-button-group>
<md-button-group variant="connected" selection="multiple"><md-button icon="format_bold" aria-label="Bold"></md-button>...</md-button-group>
FABs
A floating action button (FAB) holds the primary action on a screen.
<md-fab size="baseline" color="primary-container" icon="add" aria-label="Create"></md-fab>
Extended FABs
Extended FABs show a label next to the icon. Collapse them to the icon when space is tight.
<md-fab variant="extended" size="baseline" icon="add" label="Compose"></md-fab>
Icon buttons
Icon buttons perform compact actions. Toggle icon buttons change shape and fill when selected.
<md-icon-button variant="standard" icon="favorite" aria-label="Favorite"></md-icon-button>
<md-icon-button toggle variant="tonal" icon="bookmark" selected-icon="bookmark_added" aria-label="Bookmark"></md-icon-button>
<md-icon-button size="m" variant="filled" icon="search" aria-label="Search"></md-icon-button>
Segmented buttons
Segmented buttons help people select options, switch views, or sort elements. Expressive leaves them unchanged and recommends connected button groups for new designs.
<md-segmented-button items='["Day","Week","Month","Year"]' selected-index="0"></md-segmented-button>
<md-segmented-button multi-select items='[{"label":"Walk","icon":"directions_walk"},{"label":"Ride","icon":"directions_bus"},{"label":"Drive","icon":"directions_car"}]' selected-indices="[0]"></md-segmented-button>
Split button
A split button pairs a primary action with a menu of related actions.
<md-split-button label="Save" icon="save" items='[{"icon":"cloud_upload","label":"Save to Cloud"},{"icon":"download","label":"Export as JSON"}]'></md-split-button>
<md-split-button variant="outlined" size="m" label="Outlined" icon="edit"></md-split-button>
Communication
Badges, progress, snackbars, and tooltips keep people informed.
Badges
Badges show notifications, counts, or status information on navigation items and icons.
<md-icon-button aria-label="Mail, 4 new"><md-badge label="4">mail</md-badge></md-icon-button>
Loading indicator
Loading indicators show progress for short waits, cycling through a sequence of morphing shapes.
<md-loading-indicator variant="contained" size="m"></md-loading-indicator>
Progress indicators
Progress indicators show the status of a process. A wave adds expression to long waits.
<md-progress-indicator type="linear" variant="wavy" value="68"></md-progress-indicator>
<md-progress-indicator type="circular" variant="wavy" value="70"></md-progress-indicator>
Snackbar
Snackbars show short updates about app processes at the bottom of the screen.
<md-snackbar id='sample-snackbar' message='Document archived.' action-label='Undo' with-dismiss-action></md-snackbar>
<md-snackbar id='saved-snackbar' message='Changes saved.'></md-snackbar>
<md-snackbar id='connection-snackbar' message='You are offline. Your changes will sync when you reconnect.' action-label='View saved documents' with-dismiss-action action-on-new-line></md-snackbar>
Tooltips
Tooltips show brief labels or messages.
<md-button id="save-tooltip-anchor" label="Save document"></md-button>
<md-tooltip for="save-tooltip-anchor" caret text="Save changes to this document"></md-tooltip>
Containment
Cards, sheets, dialogs, lists, and dividers hold and organize content.
Bottom sheets
Bottom sheets show secondary content anchored to the bottom of the screen.
Choose how you would like to share this item with your team.
<md-bottom-sheet headline="Options"></md-bottom-sheet>
Cards
Cards display content and actions about a single subject.
Glacier hike
Saturday · 3 hours
A guided walk across the ice, with gear included.
<md-card variant="filled" interactive><h3 class="card-headline">Glacier hike</h3>...</md-card>
Weekly summary
Activity
You walked 42 km this week, 6 km more than last week.
<md-card variant="elevated" interactive><h3 class="card-headline">Weekly summary</h3>...</md-card>
Book club
Thursday · 19:00
This month: a novel about a lighthouse keeper.
<md-card variant="outlined" interactive><h3 class="card-headline">Book club</h3>...</md-card>
Storage almost full
Photos
Free up space to keep backing up your photos.
<md-card variant="filled"><h3 class="card-headline">Storage almost full</h3>...</md-card>
Delivery update
Order 2048
Your package arrives today before 18:00.
<md-card variant="elevated"><h3 class="card-headline">Delivery update</h3>...</md-card>
New sign-in
Today at 09:41
Your account was used on a new device.
<md-card variant="outlined"><h3 class="card-headline">New sign-in</h3>...</md-card>
Carousel
Carousels show a collection of items that can be scrolled on and off the screen.
<md-carousel preferred-item-width="186" item-spacing="8" content-padding="16"><img src="…" alt="…"></md-carousel>
<md-carousel layout="uncontained" item-width="186" item-spacing="8"><img src="…" alt="…"></md-carousel>
<md-carousel layout="hero" item-spacing="8"><img src="…" alt="…"></md-carousel>
<md-carousel layout="multi-aspect" item-spacing="8" content-padding="16"><img style="width:305px" src="…" alt="…"></md-carousel>
Dialogs
Dialogs provide important prompts in a user flow.
<md-dialog id="dialog" headline="Delete album?" supporting-text="Delete this album permanently?" confirm-label="Delete"></md-dialog> document.querySelector('#dialog').show();
Divider
Dividers are thin lines that group content in lists or other containers.
<md-divider></md-divider> <md-divider inset></md-divider> <md-divider inset="middle"></md-divider>
Expansion panel
Expansion panels show a summary and reveal details on demand.
Web extension. Material 3 has no component with this name; this one is composed from Material components and follows their specs.
Orders placed before noon ship the same day. You can change the delivery address until the order ships.
Start a return from your order history. Refunds go back to the original payment method.
Keep your receipt. Repairs and replacements are covered for two years from the date of purchase.
<md-expansion-panel headline="Shipping" supporting-text="Arrives in 3–5 business days">...</md-expansion-panel>
Lists
Lists are continuous, vertical indexes of text and images.
<md-list-item icon="inbox" headline="Inbox" trailing-text="24" interactive></md-list-item>
<md-list variant="segmented" selection-mode="single">…</md-list>
<md-list-item headline="Messages"><md-switch slot="end" checked></md-switch></md-list-item>
Side sheets
Side sheets show secondary content anchored to the side of the screen.
Properties of the selected file.
<md-side-sheet headline="Filter" divider><md-button slot="actions" variant="filled" label="Save"></md-button></md-side-sheet>
The content beside a standard side sheet narrows as the sheet slides in and widens as it leaves.
<md-side-sheet variant="standard" open headline="Filters"></md-side-sheet>
Navigation
App bars, navigation components, tabs, and toolbars move people through an app.
App bars
Top app bars show the title and actions for the current screen. Bottom app bars hold actions at the bottom of the screen.
<md-top-app-bar headline='Page title' variant='small'><md-icon-button slot='leading' icon='menu' aria-label='Open navigation'></md-icon-button><md-icon-button slot='trailing' icon='search' aria-label='Search'></md-icon-button><md-icon-button slot='trailing' icon='more_vert' aria-label='More options'></md-icon-button></md-top-app-bar>
<md-top-app-bar id='scroll-top-app-bar' data-top-app-bar-scroll='top-app-bar-content' style='max-height: 300px;' headline='Medium top bar' variant='medium-flexible' subtitle='Expanded context subtitle'><md-icon-button slot='leading' icon='arrow_back' aria-label='Back'></md-icon-button><md-icon-button slot='trailing' icon='more_vert' aria-label='More options'></md-icon-button></md-top-app-bar>
<md-top-app-bar headline='Library' variant='center-aligned'><md-icon-button slot='leading' icon='arrow_back' aria-label='Back'></md-icon-button><md-icon-button slot='trailing' icon='more_vert' aria-label='More options'></md-icon-button></md-top-app-bar>
<md-top-app-bar headline='Your library' variant='medium'><md-icon-button slot='leading' icon='menu' aria-label='Open navigation'></md-icon-button><md-icon-button slot='trailing' icon='search' aria-label='Search'></md-icon-button></md-top-app-bar>
<md-top-app-bar headline='Saved places' variant='large'><md-icon-button slot='leading' icon='arrow_back' aria-label='Back'></md-icon-button><md-icon-button slot='trailing' icon='more_vert' aria-label='More options'></md-icon-button></md-top-app-bar>
<md-top-app-bar headline='Your space' variant='large-flexible' subtitle='Everything in one place'><md-icon-button slot='leading' icon='menu' aria-label='Open navigation'></md-icon-button><md-icon-button slot='trailing' icon='search' aria-label='Search'></md-icon-button></md-top-app-bar>
<md-bottom-app-bar id='scroll-bottom-app-bar' data-bottom-app-bar-scroll='bottom-app-bar-content' aria-label='Document actions'><md-icon-button icon='menu' aria-label='Menu'></md-icon-button><md-icon-button icon='search' aria-label='Search'></md-icon-button><md-icon-button icon='edit' aria-label='Edit'></md-icon-button><md-fab slot='fab' icon='add' aria-label='Add document' color='secondary-container' elevation='bottom-app-bar'></md-fab></md-bottom-app-bar>
<md-bottom-app-bar variant='flexible' aria-label='Flexible document actions'><md-icon-button icon='menu' aria-label='Menu'></md-icon-button><md-icon-button icon='search' aria-label='Search'></md-icon-button><md-icon-button icon='favorite' aria-label='Favorite'></md-icon-button><md-icon-button icon='more_vert' aria-label='More options'></md-icon-button></md-bottom-app-bar>
Paginator
A paginator moves through pages of data and sets how many items each page shows.
Web extension. Material 3 has no component with this name; this one is composed from Material components and follows their specs.
<md-paginator length="125" page-size="10" page-index="0"></md-paginator>
Search
Search lets people enter a query and get relevant information. The bar can stand alone or sit in an app bar.
<md-search-bar placeholder="Search components" suggestions='[{"label":"Buttons","icon":"history"}]'></md-search-bar>
<md-search-bar full-screen placeholder="Search mail" suggestions='[{"label":"Invoices","icon":"history"}]'></md-search-bar>
<md-app-bar-with-search scroll-behavior="enter-always"><md-icon-button slot="navigation" icon="menu"></md-icon-button><md-search-bar full-screen contained></md-search-bar><md-icon-button slot="actions" icon="more_vert"></md-icon-button></md-app-bar-with-search> bar.scrollTarget = list;
Stepper
A stepper divides a task into numbered steps.
Web extension. Material 3 has no component with this name; this one is composed from Material components and follows their specs.
Enter the details for your new account.
Choose what you want to hear about.
Everything is ready. Go back to change a step, or start over.
<md-stepper active-step="0">
<md-step label="Account" description="Your name and email">...</md-step>
<md-step label="Preferences" description="Notifications">...</md-step>
<md-step label="Review" description="Confirm and create">...</md-step>
</md-stepper>
Tabs
Tabs organize content across different screens and views.
<md-tabs aria-label="Travel" tabs='[{"icon":"flight","label":"Flights"},{"icon":"hotel","label":"Hotels"}]'></md-tabs>
<md-tabs variant="secondary" tabs='[{"label":"Overview"},{"label":"Specs"}]'></md-tabs>
<md-tabs scrollable aria-label="Music library" tabs='[{"label":"Songs"},{"label":"Albums"},{"label":"Artists"},{"label":"Playlists"}]'></md-tabs>
<md-tabs icon-position="start" tabs='[{"icon":"inbox","label":"Inbox"},{"icon":"star","label":"Starred"}]'></md-tabs>
Toolbars
Toolbars show frequently used actions relevant to the current page.
<md-toolbar variant="floating" expanded><md-icon-button slot="leading" icon="undo" aria-label="Undo"></md-icon-button><md-icon-button variant="filled" icon="edit" aria-label="Edit"></md-icon-button><md-icon-button slot="trailing" icon="redo" aria-label="Redo"></md-icon-button></md-toolbar>
<md-toolbar id="actions" variant="floating" color="vibrant" expanded><md-icon-button icon="edit" aria-label="Edit"></md-icon-button><md-fab slot="fab" icon="add" aria-label="Toggle actions"></md-fab></md-toolbar>
const toolbar = document.querySelector('#actions');
toolbar.querySelector('[slot="fab"]').addEventListener('click', () => toolbar.toggle());
<md-toolbar id="tools" variant="floating" orientation="vertical" expanded><md-icon-button icon="draw" aria-label="Draw"></md-icon-button><md-fab slot="fab" icon="add" aria-label="Toggle tools"></md-fab></md-toolbar>
<script>const tools = document.querySelector('#tools'); tools.querySelector('[slot="fab"]').addEventListener('click', () => tools.toggle());</script>
toolbar.shape = {type: 'rounded', corners: 16}; // or {type: 'cut', corners: 16}; toolbar.shape = null; // restore full corners
<md-toolbar variant="docked" color="vibrant" aria-label="Text formatting"><md-icon-button icon="format_bold" toggle selected aria-label="Bold"></md-icon-button></md-toolbar>
toolbar.scrollExpansion = new ToolbarScrollExpansion({expanded: true, onExpand: () => toolbar.expand(), onCollapse: () => toolbar.collapse()}); toolbar.scrollTarget = document.querySelector('#scroll-expand-content');
toolbar.scrollBehavior = new FloatingToolbarScrollBehavior({exitDirection: 'bottom'}); toolbar.scrollTarget = document.querySelector('#scroll-hide-content');
Selection
Checkboxes, chips, pickers, menus, radio buttons, sliders, and switches let people choose.
Checkbox
Checkboxes let people select one or more items from a list, or turn an item on or off.
<md-checkbox aria-label="Subscribe to newsletter" checked></md-checkbox>
Chips
Chips help people enter information, make selections, filter content, or trigger actions.
<md-chip variant="filter" label="Top rated" selected></md-chip>
<md-chip variant="input" label="Contact" removable></md-chip>
<md-chip variant="suggestion" label="Walking"></md-chip>
Date pickers
Date pickers let people select a date, or a range of dates.
<md-date-picker variant="docked" inline></md-date-picker>
<md-date-picker id="date" variant="modal"></md-date-picker> document.querySelector('#date').show();
<md-date-picker variant="range" inline></md-date-picker>
Radio button
Radio buttons let people select one option from a set.
<md-radio-button name="plan" label="Option 1" checked></md-radio-button>
Sliders
Sliders let people make selections from a range of values.
<md-slider range range-start="20" range-end="80"></md-slider>
<md-slider centered min="-100" max="100" value="45"></md-slider>
<md-slider value="65" labeled></md-slider>
<md-slider steps="9" value="40"></md-slider>
<md-slider orientation="vertical" top-to-bottom="false" value="65"></md-slider>
<md-slider track-height="36" track-corner-size="12" stop-indicator="false"></md-slider>
Switch
Switches toggle the selection of an item on or off.
<md-switch checked icon="check"></md-switch>
Time pickers
Time pickers help people select and set a specific time.
<md-time-picker id="time" variant="dial"></md-time-picker> document.querySelector('#time').show();
<md-time-picker variant="input" is-24-hour inline></md-time-picker>
<md-time-picker variant="horizontal" inline></md-time-picker>
Text inputs
Text fields and the controls built on them let people enter and select text.
Autocomplete
An editable text field that suggests matching options as people type.
Web extension. Material 3 has no component with this name; this one is composed from Material components and follows their specs.
<md-autocomplete label="Framework" options='["React", "Vue"]'></md-autocomplete>
Select
A read-only text field that opens a menu of options.
Web extension. Material 3 has no component with this name; this one is composed from Material components and follows their specs.
<md-select label="Architecture" value="compose"><md-option value="compose">Compose</md-option></md-select>
<md-select label="Roles" multiple value="dev,design">...</md-select>
Text fields
Text fields let people enter text into a UI.
<md-text-field float-label="always" label="Title"></md-text-field>
currency="USD" or suffix-text="EUR" to auto-derive symbols, or customize manually.
<md-text-field single-line label="Price" currency="USD"></md-text-field>
<md-text-field variant="outlined" type="email" label="Email" placeholder="name@example.com"></md-text-field>
<md-text-field variant="filled" type="email" label="Email" placeholder="name@example.com"></md-text-field>
<md-text-field variant="outlined" type="password" label="Password" error error-text="Password is too weak" maxlength="20"></md-text-field>
<md-text-field label="Notes" min-lines="2" max-lines="4"></md-text-field>
<md-text-field variant="filled" label-position="above" label="Description"></md-text-field>
Styles
Color and shape are the foundations every component builds on.
Color
Dynamic color creates a full scheme of color roles from one seed color.
<md-theme primary-seed="#6750A4" palette-variant="tonal-spot"></md-theme>
Shape
Expressive shapes from the Material shape library add emphasis and personality.
<md-shape name="sunny" size="48px" color="primary"></md-shape>