Material Design 3 Expressive — Built for the Web
39 zero-dependency Web Components ported directly from Android Jetpack Compose 1.4+ source code. Features CAM16 HCT dynamic theming and spring physics.
verified Why MD3E Web?
Core architectural principles of the Material Design 3 Expressive web implementation.
1. Zero Dependencies
Shadow DOM v1, Custom Elements v1, and CSS Custom Properties. No build step required, runs natively anywhere.
2. CAM16 Dynamic HCT
Derives 5 tonal palettes with guaranteed WCAG 2.1 AA/AAA contrast ratios from a single seed hex color.
3. Android Compose 1:1 Spring Physics
Organic and natural motion curves powered by a damped harmonic oscillator mathematical model.
4. Cross-Framework Ready
Seamless form integration and event handling across React 19, Vue 3, Svelte 5, Angular 17+, and Vanilla HTML/JS.
This project is an independent open-source web adaptation and personal learning project. It is not affiliated with, endorsed by, or sponsored by Google LLC. The wavy progress and spring physics algorithms are derived under the Apache-2.0 license from the Android Open Source Project (AOSP) and Material Components for Android source trees.
Getting Started with MD3E
A production-ready suite of 36+ Material Design 3 Expressive Web Components featuring CAM16 dynamic color theming and organic spring physics. Run natively in any modern browser with zero build step requirements.
download 1. Quick Installation
Choose the integration method that fits your project architecture.
Option A: Package Manager (Recommended)
Install via npm, pnpm, or bun for React, Vue, Svelte, Next.js, or Vite apps.
# Install with NPM
npm install @materialwebunofficial/md3e-web
# or with PNPM
pnpm add @materialwebunofficial/md3e-web
# or with Bun
bun add @materialwebunofficial/md3e-web
Option B: Zero-Build CDN
Embed directly into any HTML page with zero bundlers or build steps required.
<!-- M3E Design Tokens -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@materialwebunofficial/md3e-web/dist/tokens.min.css">
<link rel="stylesheet" href="src/icons/material-symbols.css">
<!-- M3E Web Components -->
<script type="module" src="https://cdn.jsdelivr.net/npm/@materialwebunofficial/md3e-web/dist/md3-expressive.min.js"></script>
play_arrow 2. 30-Second Quickstart Template
Copy and paste this minimal boilerplate into an index.html file to get immediate results.
<!DOCTYPE html>
<html lang="en" data-theme="dark" data-theme-scheme="expressive">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MD3E Web App</title>
<!-- 1. CSS Design Tokens & Material Symbols -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@materialwebunofficial/md3e-web/dist/tokens.min.css">
<!-- 2. Web Components Suite (All 36 Components) -->
<script type="module" src="https://cdn.jsdelivr.net/npm/@materialwebunofficial/md3e-web/dist/md3-expressive.min.js"></script>
</head>
<body style="background: var(--md-sys-color-background); color: var(--md-sys-color-on-background); padding: 32px; font-family: Roboto, sans-serif;">
<h1 class="md-headline-medium">Hello MD3 Expressive</h1>
<div style="display: flex; gap: 12px; align-items: center; margin: 20px 0;">
<md-button variant="filled" icon="favorite" label="Expressive Button"></md-button>
<md-button variant="tonal" icon="share" label="Tonal Action"></md-button>
</div>
<md-progress-indicator type="linear" variant="wavy" value="70"></md-progress-indicator>
</body>
</html>
integration_instructions 3. Framework Integration
Since MD3E uses native W3C Custom Elements, it operates seamlessly with all major UI frameworks.
'use client';
import { useEffect } from 'react';
import '@materialwebunofficial/md3e-web/src/tokens/bundle.css';
import '@materialwebunofficial/md3e-web/src/icons/material-symbols.css';
export default function ActionCard() {
useEffect(() => {
// Dynamic import registers custom elements in the browser
import('@materialwebunofficial/md3e-web');
}, []);
return (
<div style={{ padding: '16px' }}>
<md-card variant="elevated" interactive>
<md-button variant="filled" size="m" icon="check" label="Confirm"></md-button>
</md-card>
</div>
);
}
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
vue({
template: {
compilerOptions: {
// Tell Vue compiler to treat md- tags as native Web Components
isCustomElement: (tag) => tag.startsWith('md-')
}
}
})
]
});
<script>
import '@materialwebunofficial/md3e-web/src/tokens/bundle.css';
import '@materialwebunofficial/md3e-web';
let progress = $state(65);
</script>
<md-slider min="0" max="100" bind:value={progress}></md-slider>
<md-progress-indicator type="linear" variant="wavy" value={progress}></md-progress-indicator>
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="Angular MD3E" icon="bolt"></md-button>`
})
export class AppComponent {}
import { applyDynamicTheme } from '@materialwebunofficial/md3e-web';
// Apply CAM16 dynamic theming with single function call
applyDynamicTheme('#6750A4', true, 'expressive');
code 4. Core JavaScript APIs
Programmatically control dynamic theming and spring physics animations.
import { applyDynamicTheme, SpringPhysics } from '@materialwebunofficial/md3e-web';
// 1. Apply dynamic tonal color palette from any seed hex color
applyDynamicTheme('#00639B', true, 'expressive');
// 2. Generate smooth WAAPI keyframes with damped harmonic oscillator
const keyframes = SpringPhysics.generateKeyframes({
stiffness: 800,
dampingRatio: 0.7
});
// 3. Animate any DOM element natively
document.querySelector('#my-element').animate(keyframes, {
duration: 450,
fill: 'forwards'
});
palette 5. Key Design Tokens Reference
Core CSS Custom Properties available globally across your application.
| CSS Variable (Token) | Description | Example Usage |
|---|---|---|
--md-sys-color-primary |
Primary accent brand color | Filled Buttons, Selected FABs, Active Indicators |
--md-sys-color-surface-container |
Default surface and card background | Cards, Sheets, Dialogs, Content Panes |
--md-sys-motion-easing-expressive-spatial |
Organic expressive motion bezier curve | Expanding surfaces, modal entrances, layout shifts |
--md-sys-shape-corner-extra-large |
28dp expressive corner radius | Large containers, cards, bottom sheets |
--md-sys-typescale-display-large |
57px / 400 weight / 64px line-height (Brand font) | Large expressive hero typography (.md-display-large) |
--md-sys-typescale-headline-medium-emphasized |
28px / 500 weight / 36px line-height (Brand font) | Emphasized section headings (.md-headline-medium-emphasized) |
--md-sys-typescale-title-medium-emphasized |
16px / 700 weight / 24px line-height / 0.15px tracking | Emphasized card & list titles (.md-title-medium-emphasized) |
--md-sys-typescale-body-large |
16px / 400 weight / 24px line-height / 0.5px tracking | Standard readable long-form text (.md-body-large) |
--md-sys-typescale-label-large-emphasized |
14px / 700 weight / 20px line-height / 0.1px tracking | High-emphasis interactive CTA labels (.md-label-large-emphasized) |
M3 Expressive Typescale System (26 Styles — 13 Baseline + 13 Emphasized)
Ported directly from AndroidX TypeScaleTokens.kt. All styles support both CSS Custom Properties and utility classes (.md-<name> / .md-typescale-<name>).
toolbar App bars
Top and bottom app bars provide access to key destinations and screen actions.
<md-top-app-bar headline="Page Title" variant="small"></md-top-app-bar>
<md-top-app-bar headline="Medium Top Bar" variant="medium" subtitle="Subtitle"></md-top-app-bar>
<md-bottom-app-bar></md-bottom-app-bar>
notifications Badges
Dot badges and numeric count badges providing non-intrusive status indicators.
<md-badge label="4"></md-badge>
smart_button Buttons
Buttons prompt most actions in a UI with 5 expressive sizes and spring morphing.
<md-button variant="filled" label="Button" icon="add"></md-button>
<md-button size="m" variant="filled" label="Button"></md-button>
<md-fab variant="medium" color="primary" icon="add"></md-fab>
<md-fab variant="extended" color="primary" icon="add" label="Compose"></md-fab>
<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>
<md-segmented-button items="Day,Week,Month,Year" selected-index="0"></md-segmented-button>
<md-segmented-button multi-select items="Bold,Italic,Underline" selected-indices="[0,1,2]"></md-segmented-button>
<md-split-button label="Save" icon="save" items='[{"icon":"cloud_upload","label":"Save to Cloud"},{"icon":"download","label":"Export as JSON"}]'></md-split-button>
crop_square Cards
Cards contain content and actions about a single subject, available in both interactive and non-interactive variants.
Filled Card (Interactive)
Clickable container with tactile spring press and hover response.
<md-card interactive variant="filled"><h3 class="md-title-medium">Filled Card</h3></md-card>
Elevated Card (Interactive)
Elevated card lifting to Level 2 shadow with spring motion on hover.
<md-card interactive variant="elevated"><h3 class="md-title-medium">Elevated Card</h3></md-card>
Outlined Card (Interactive)
Crisp 1dp outline variant with interactive click feedback.
<md-card interactive variant="outlined"><h3 class="md-title-medium">Outlined Card</h3></md-card>
Filled Card (Non-Interactive)
Static surface container for grouping purely informational content.
<md-card variant="filled"><h3 class="md-title-medium">Filled Card</h3></md-card>
Elevated Card (Non-Interactive)
Fixed Level 1 shadow elevation for non-clickable content grouping.
<md-card variant="elevated"><h3 class="md-title-medium">Elevated Card</h3></md-card>
Outlined Card (Non-Interactive)
Static 1dp outline border matching outline-variant token.
<md-card variant="outlined"><h3 class="md-title-medium">Outlined Card</h3></md-card>
view_carousel Carousel
Multi-Browse Carousel with 280dp hero card morphing and spring physics.
<md-carousel variant="multi-browse" items='[{"title":"City"},{"title":"Nature"}]'></md-carousel>
label Chips
Assist, Filter, Input, Suggestion, and Action chips with 32dp height and 48dp touch targets.
<md-chip variant="filter" label="Top Rated" selected></md-chip>
<md-chip variant="input" label="Contact" dismissible></md-chip>
calendar_month Date Pickers
100% faithful AndroidX Compose DatePicker implementations.
<md-date-picker></md-date-picker>
<md-date-picker headline="Select Date"></md-date-picker>
<md-date-picker range headline="Select Range"></md-date-picker>
schedule Time Pickers
100% faithful AndroidX Compose TimePicker with dial, keyboard, and horizontal modes.
<md-time-picker format="12h"></md-time-picker>
<md-time-picker format="12h" input-mode="keyboard"></md-time-picker>
<md-time-picker format="24h" orientation="horizontal"></md-time-picker>
open_in_new Dialogs
Modal dialogs with title, supporting text, icon, and action buttons.
<md-button variant="filled">Dialogs</md-button>
remove Divider
A thin line that groups content in lists and layouts.
Content Section 1
Content Section 2 (Inset Divider)
Content Section 3
<md-divider></md-divider>
list Lists
Continuous vertical indexes of text and images.
<md-button variant="filled">Lists</md-button>
progress_activity Progress & Loading
100% faithful AndroidX Compose LoadingIndicator (7 MaterialShapes morph), Linear/Circular Standard & Expressive Wavy indicators.
<md-progress-indicator type="linear" variant="wavy" value="68"></md-progress-indicator>
<md-progress-indicator type="circular" variant="wavy" value="70"></md-progress-indicator>
<md-loading-indicator variant="contained" size="m" color="primary"></md-loading-indicator>
check_box Selection Controls
Checkboxes, Radio buttons, and Switches with spring motion.
<md-checkbox label="Subscribe to newsletter" checked></md-checkbox>
<md-radio-button name="plan" label="Option 1" checked></md-radio-button>
<md-switch selected show-icons></md-switch>
search Search
Search bar allows users to enter search queries and view suggestions.
<md-search-bar placeholder="Search..."></md-search-bar>
horizontal_rule Sheets
Bottom sheet and side sheet interactive contextual surfaces.
Choose how you would like to share this item with your team.
<md-bottom-sheet headline="Options"></md-bottom-sheet>
Detailed properties and metadata for the selected item.
<md-side-sheet headline="Filter"></md-side-sheet>
tune Sliders
Expressive sliders with 5 sizes (XS 16dp to XL 48dp), centered track, and 4dp discrete stops.
<md-slider min="0" max="100" value="45"></md-slider>
<md-slider min="0" max="100" step="10" value="60" discrete></md-slider>
announcement Snackbar
Snackbars provide brief messages about app processes at the bottom of the screen.
<md-snackbar message="Item added to wishlist" action-label="Undo"></md-snackbar>
tab Tabs
Tabs organize content across different screens and data views.
<md-tabs variant="primary" tabs='[{"label":"Flights"},{"label":"Trips"}]'></md-tabs>
<md-tabs variant="secondary" tabs='[{"label":"Overview"},{"label":"Specs"}]'></md-tabs>
edit Text Fields
Outlined and Filled text fields with floating labels, leading/trailing icons, and supporting text.
<md-text-field variant="outlined" label="Email" placeholder="name@example.com"></md-text-field>
<md-text-field variant="filled" label="Username" placeholder="Enter username"></md-text-field>
<md-text-field variant="outlined" label="Password" error error-text="Password is too weak" maxlength="20"></md-text-field>
density_medium Toolbars
Toolbars display frequently used actions relevant to the current page.
<md-toolbar color="surface-container"></md-toolbar>
chat_bubble Tooltips
Tooltips display brief labels or messages anchored to interactive elements.
<md-tooltip text="Helpful tooltip"><button>Hover</button></md-tooltip>
palette Theme & color
Material 3 Dynamic Color CAM16 / HCT engine and Compose theme composables.
Select official presets, adjust HCT sliders, or pick RGB/Hex values to dynamically recolor the entire UI in real time.
<md-theme seed="#6750A4" scheme="tonal-spot"></md-theme>