| name | google-material-design |
| description | Design interfaces following Google's Material Design system, the unified visual language bridging digital and physical worlds. Emphasizes bold graphic design, intentional motion, adaptive layouts, and the material metaphor. Use when building modern, accessible, delightful user interfaces across platforms. |
Google Material Design
Overview
Material Design is Google's open-source design system that bridges the gap between the physical and digital worlds. Introduced in 2014 and evolved through Material Design 2 (2018) and Material Design 3 (2021), it provides a comprehensive framework for building beautiful, functional, and accessible interfaces across all platforms.
References
Core Philosophy
"Material is the metaphor."
"Bold, graphic, intentional."
"Motion provides meaning."
"Adaptive design, delightful experiences."
Material Design creates a visual language that synthesizes classic principles of good design with the innovation and possibility of technology and science.
The Material Metaphor
Physical World Inspiration
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ MATERIAL = DIGITAL PAPER + INK + PHYSICAL PROPERTIES โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโ Light โ
โ โ Surface โ โโโ casts shadows โ
โ โ (z=2) โ based on elevation โ
โ โโโโโโโโโโโ โ
โ โ โ
โ โ Elevation โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Ground Plane (z=0) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โข Surfaces exist in 3D space with depth โ
โ โข Material has physical properties and affordances โ
โ โข Shadows communicate spatial relationships โ
โ โข Content is printed on material, not within it โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Elevation System
Elevation (dp) Component Examples Shadow Intensity
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
0dp Background, disabled None
1dp Card (resting), Search bar Subtle
2dp Card (raised), Button Light
3dp Refresh indicator Light-Medium
4dp App Bar Medium
6dp FAB (resting), Snackbar Medium
8dp Bottom sheet, Menu Pronounced
12dp FAB (pressed), Dialog Strong
16dp Nav drawer Strong
24dp Modal bottom sheet Maximum
Design Principles
1. Material is the Metaphor
.surface {
background: var(--md-sys-color-surface);
box-shadow: var(--md-sys-elevation-level2);
border-radius: var(--md-sys-shape-corner-medium);
}
.content-on-surface {
color: var(--md-sys-color-on-surface);
}
2. Bold, Graphic, Intentional
Typography Hierarchy (Material 3)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Display Large 57sp Headlines for hero moments
Display Medium 45sp Large display text
Display Small 36sp Smaller display text
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Headline Large 32sp High-emphasis text
Headline Medium 28sp Medium emphasis headers
Headline Small 24sp Smaller headlines
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Title Large 22sp Prominent titles
Title Medium 16sp Medium titles
Title Small 14sp Smaller titles, tabs
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Label Large 14sp Buttons, prominent labels
Label Medium 12sp Navigation labels
Label Small 11sp Timestamps, hints
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Body Large 16sp Primary body text
Body Medium 14sp Secondary body text
Body Small 12sp Captions, annotations
3. Motion Provides Meaning
const MaterialMotion = {
duration: {
short1: 50,
short2: 100,
short3: 150,
short4: 200,
medium1: 250,
medium2: 300,
medium3: 350,
medium4: 400,
long1: 450,
long2: 500,
long3: 550,
long4: 600,
},
easing: {
emphasized: 'cubic-bezier(0.2, 0.0, 0, 1.0)',
emphasizedDecelerate: 'cubic-bezier(0.05, 0.7, 0.1, 1.0)',
emphasizedAccelerate: 'cubic-bezier(0.3, 0.0, 0.8, 0.15)',
standard: 'cubic-bezier(0.2, 0.0, 0, 1.0)',
standardDecelerate: 'cubic-bezier(0, 0, 0, 1)',
standardAccelerate: 'cubic-bezier(0.3, 0, 1, 1)',
},
patterns: {
containerTransform: {
use: 'Element expands into a new screen',
duration: 'medium2',
easing: 'emphasized',
},
sharedAxis: {
use: 'Navigation between related destinations',
duration: 'medium1',
easing: 'emphasized',
},
fadeThrough: {
use: 'Switching between unrelated content',
duration: 'medium1',
easing: 'emphasized',
},
fade: {
use: 'UI elements appearing or disappearing',
duration: 'short4',
easing: 'standard',
},
},
};
function containerTransform(element, options) {
const { duration, easing } = MaterialMotion.patterns.containerTransform;
return element.animate([
{ transform: 'scale(0.85)', opacity: 0 },
{ transform: 'scale(1)', opacity: 1 },
], {
duration: MaterialMotion.duration[duration],
easing: MaterialMotion.easing[easing],
fill: 'forwards',
});
}
Color System (Material 3 Dynamic Color)
Tonal Palettes
Source Color โ Tonal Palette โ Color Scheme
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Primary Source (#6750A4)
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Tonal Palette: Primary โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ 0 10 20 30 40 50 60 70 80 90 95 100โ
โ โโโโ โโโโ โโโโ โโโโ โโโโ โโโโ โโโโ โโโโ โโโโ โโโโ โโโโ โ
โ Darkest โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโบ Lightest โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
Light Scheme: Dark Scheme:
primary: tone40 primary: tone80
onPrimary: tone100 onPrimary: tone20
primaryContainer: tone90 primaryContainer: tone30
onPrimaryContainer: tone10 onPrimaryContainer: tone90
Color Roles
:root {
--md-sys-color-primary: #6750A4;
--md-sys-color-on-primary: #FFFFFF;
--md-sys-color-primary-container: #EADDFF;
--md-sys-color-on-primary-container: #21005D;
--md-sys-color-secondary: #625B71;
--md-sys-color-on-secondary: #FFFFFF;
--md-sys-color-secondary-container: #E8DEF8;
--md-sys-color-on-secondary-container: #1D192B;
--md-sys-color-tertiary: #7D5260;
--md-sys-color-on-tertiary: #FFFFFF;
--md-sys-color-tertiary-container: #FFD8E4;
--md-sys-color-on-tertiary-container: #31111D;
--md-sys-color-error: #B3261E;
--md-sys-color-on-error: #FFFFFF;
--md-sys-color-error-container: #F9DEDC;
--md-sys-color-on-error-container: #410E0B;
--md-sys-color-surface: #FFFBFE;
--md-sys-color-on-surface: #1C1B1F;
--md-sys-color-surface-variant: #E7E0EC;
--md-sys-color-on-surface-variant: #49454F;
--md-sys-color-outline: #79747E;
--md-sys-color-outline-variant: #CAC4D0;
}
Dynamic Color from Content
class MaterialColorScheme {
constructor(sourceColor) {
this.source = sourceColor;
this.palette = this.generateTonalPalette(sourceColor);
}
generateTonalPalette(color) {
const hct = rgbToHct(color);
return {
0: hctToRgb({ ...hct, tone: 0 }),
10: hctToRgb({ ...hct, tone: 10 }),
20: hctToRgb({ ...hct, tone: 20 }),
30: hctToRgb({ ...hct, tone: 30 }),
40: hctToRgb({ ...hct, tone: 40 }),
50: hctToRgb({ ...hct, tone: 50 }),
60: hctToRgb({ ...hct, tone: 60 }),
70: hctToRgb({ ...hct, tone: 70 }),
80: hctToRgb({ ...hct, tone: 80 }),
90: hctToRgb({ ...hct, tone: 90 }),
95: hctToRgb({ ...hct, tone: 95 }),
99: hctToRgb({ ...hct, tone: 99 }),
100: hctToRgb({ ...hct, tone: 100 }),
};
}
getLightScheme() {
return {
primary: this.palette[40],
onPrimary: this.palette[100],
primaryContainer: this.palette[90],
onPrimaryContainer: this.palette[10],
};
}
getDarkScheme() {
return {
primary: this.palette[80],
onPrimary: this.palette[20],
primaryContainer: this.palette[30],
onPrimaryContainer: this.palette[90],
};
}
}
Component Architecture
Anatomy of a Material Component
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ BUTTON ANATOMY โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ [Icon] Label Text โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ โ
โ โ โ โ โ
โ โ Leading Icon (optional) โ โ
โ โ โ โ
โ โ Label text (required) Container โ
โ โ (required) โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ States: Enabled, Disabled, Hovered, โ
โ Focused, Pressed โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Button Variants
interface ButtonProps {
variant: 'elevated' | 'filled' | 'tonal' | 'outlined' | 'text';
icon?: React.ReactNode;
children: React.ReactNode;
disabled?: boolean;
onClick?: () => void;
}
const ElevatedButton = styled.button`
background: var(--md-sys-color-surface-container-low);
color: var(--md-sys-color-primary);
box-shadow: var(--md-sys-elevation-level1);
border: none;
border-radius: 20px;
padding: 10px 24px;
font: var(--md-sys-typescale-label-large);
&:hover {
box-shadow: var(--md-sys-elevation-level2);
background: color-mix(
in srgb,
var(--md-sys-color-primary) 8%,
var(--md-sys-color-surface-container-low)
);
}
&:focus-visible {
outline: none;
box-shadow: var(--md-sys-elevation-level1);
background: color-mix(
in srgb,
var(--md-sys-color-primary) 12%,
var(--md-sys-color-surface-container-low)
);
}
&:active {
box-shadow: var(--md-sys-elevation-level1);
background: color-mix(
in srgb,
var(--md-sys-color-primary) 12%,
var(--md-sys-color-surface-container-low)
);
}
`;
const FilledButton = styled.button`
background: var(--md-sys-color-primary);
color: var(--md-sys-color-on-primary);
border: none;
border-radius: 20px;
padding: 10px 24px;
&:hover {
box-shadow: var(--md-sys-elevation-level1);
background: color-mix(
in srgb,
var(--md-sys-color-on-primary) 8%,
var(--md-sys-color-primary)
);
}
`;
const TonalButton = styled.button`
background: var(--md-sys-color-secondary-container);
color: var(--md-sys-color-on-secondary-container);
border: none;
border-radius: 20px;
padding: 10px 24px;
`;
const OutlinedButton = styled.button`
background: transparent;
color: var(--md-sys-color-primary);
border: 1px solid var(--md-sys-color-outline);
border-radius: 20px;
padding: 10px 24px;
`;
const TextButton = styled.button`
background: transparent;
color: var(--md-sys-color-primary);
border: none;
border-radius: 20px;
padding: 10px 12px;
`;
State Layer System
.interactive-element {
position: relative;
overflow: hidden;
}
.interactive-element::before {
content: '';
position: absolute;
inset: 0;
background: currentColor;
opacity: 0;
transition: opacity 150ms var(--md-sys-motion-easing-standard);
}
.interactive-element:hover::before {
opacity: 0.08;
}
.interactive-element:focus-visible::before {
opacity: 0.12;
}
.interactive-element:active::before {
opacity: 0.12;
}
.interactive-element[data-dragged]::before {
opacity: 0.16;
}
.interactive-element:disabled {
opacity: 0.38;
pointer-events: none;
}
.interactive-element:disabled::before {
display: none;
}
Shape System
Corner Styles
Shape Scale (Material 3)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
None (0dp) Extra Small (4dp) Small (8dp)
โโโโโโโโโโโโ โญโโโโโโโโโโโฎ โญโโโโโโโโโโโฎ
โ โ โ โ โ โ
โ โ โ โ โ โ
โ โ โ โ โ โ
โโโโโโโโโโโโ โฐโโโโโโโโโโโฏ โฐโโโโโโโโโโโฏ
Medium (12dp) Large (16dp) Extra Large (28dp)
โญโโโโโโโโโโโฎ โญโโโโโโโโโโโฎ โญโโโโโโโโโโโฎ
โ โ โ โ โ โ
โ โ โ โ โ โ
โ โ โ โ โ โ
โฐโโโโโโโโโโโฏ โฐโโโโโโโโโโโฏ โฐโโโโโโโโโโโฏ
Full (50%)
โญโโโโโฎ
โ โ
โ โ
โฐโโโโโฏ
:root {
--md-sys-shape-corner-none: 0px;
--md-sys-shape-corner-extra-small: 4px;
--md-sys-shape-corner-small: 8px;
--md-sys-shape-corner-medium: 12px;
--md-sys-shape-corner-large: 16px;
--md-sys-shape-corner-extra-large: 28px;
--md-sys-shape-corner-full: 9999px;
}
.chip { border-radius: var(--md-sys-shape-corner-small); }
.card { border-radius: var(--md-sys-shape-corner-medium); }
.dialog { border-radius: var(--md-sys-shape-corner-extra-large); }
.fab { border-radius: var(--md-sys-shape-corner-large); }
.button { border-radius: var(--md-sys-shape-corner-full); }
Adaptive Layouts
Responsive Grid System
Window Size Classes
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Compact (< 600dp) Medium (600-839dp) Expanded (840dp+)
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโ
โ โ โ โ โ Nav โ โ
โ Content โ โ Content โ โ Bar โ Content โ
โ โ โ โ โ โ โ
โ โ โ โ โ โ โ
โโโโโโโโโโโโโโโค โ โ โ โ โ
โ Nav Bar โ โโโโโโโโโโโโโโโโโโค โ โ โ
โโโโโโโโโโโโโโโ โ Nav Bar โ โ โ โ
โโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโ
4 columns 8 columns (body) 12 columns (body)
16dp margins 24dp margins 24dp margins
8dp gutters 16dp gutters 24dp gutters
Layout Implementation
import { useWindowSize } from './hooks';
type WindowSizeClass = 'compact' | 'medium' | 'expanded' | 'large' | 'extraLarge';
function getWindowSizeClass(width: number): WindowSizeClass {
if (width < 600) return 'compact';
if (width < 840) return 'medium';
if (width < 1200) return 'expanded';
if (width < 1600) return 'large';
return 'extraLarge';
}
interface AdaptiveLayoutProps {
navigation: React.ReactNode;
content: React.ReactNode;
detail?: React.ReactNode;
}
export function AdaptiveLayout({ navigation, content, detail }: AdaptiveLayoutProps) {
const { width } = useWindowSize();
const sizeClass = getWindowSizeClass(width);
if (sizeClass === 'compact') {
return (
<div className="layout-compact">
<main className="content">{content}</main>
<nav className="navigation-bar">{navigation}</nav>
</div>
);
}
if (sizeClass === 'medium') {
return (
<div className="layout-medium">
<nav className="navigation-rail">{navigation}</nav>
<main className="content">{content}</main>
</div>
);
}
return (
<div className="layout-expanded">
<nav className="navigation-drawer">{navigation}</nav>
<main className="content">{content}</main>
{detail && sizeClass !== 'expanded' && (
<aside className="detail-pane">{detail}</aside>
)}
</div>
);
}
Navigation Patterns
Navigation Components by Screen Size
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Compact Medium Expanded
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Primary Bottom Bar Rail Drawer
3-5 items 3-7 items Full labels
Secondary Modal Drawer Modal Drawer Persistent Drawer
Tertiary Tabs Tabs Tabs
Bottom Sheet Side Sheet Side Sheet
Accessibility (A11y)
Touch Targets
.touch-target {
min-width: 48px;
min-height: 48px;
display: flex;
align-items: center;
justify-content: center;
}
.icon-button {
width: 48px;
height: 48px;
padding: 12px;
}
.icon-button svg {
width: 24px;
height: 24px;
}
Color Contrast
Contrast Requirements (WCAG 2.1)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Text Size Minimum (AA) Enhanced (AAA)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Normal text 4.5:1 7:1
Large text 3:1 4.5:1
(18sp+ or 14sp bold)
UI Components 3:1 Not defined
(borders, icons)
Material Design ensures:
โข on-primary meets 4.5:1 against primary
โข on-surface meets 4.5:1 against surface
โข All semantic color pairs are accessible
Focus Indicators
.focusable {
outline: none;
position: relative;
}
.focusable:focus-visible {
outline: 3px solid var(--md-sys-color-secondary);
outline-offset: 2px;
}
.button:focus-visible {
outline: none;
}
.button:focus-visible::after {
content: '';
position: absolute;
inset: -4px;
border: 3px solid var(--md-sys-color-secondary);
border-radius: inherit;
pointer-events: none;
}
When Implementing
Always
- Use the design token system for colors, typography, and shape
- Implement all interactive states (enabled, disabled, hover, focus, pressed)
- Ensure 48dp minimum touch targets
- Provide visible focus indicators
- Use semantic color roles (primary, secondary, error) not raw values
- Apply elevation system for spatial hierarchy
- Include meaningful motion for state changes
Never
- Hard-code color values instead of tokens
- Ignore disabled states
- Create custom colors outside the tonal palette
- Skip focus states for keyboard users
- Use elevation without purpose
- Add motion that doesn't convey meaning
- Violate touch target minimums
Prefer
- Filled buttons for primary actions, text buttons for tertiary
- Tonal palette for consistent, harmonious colors
- Standard easing for most transitions
- Surface color variants over opacity for overlays
- Component library over custom implementations
- Adaptive layouts over fixed breakpoints
Mental Model
Material Design asks:
- Is it material? Does it behave like a physical surface with depth?
- Is it intentional? Does every element serve a clear purpose?
- Is it meaningful? Does motion communicate state and guide attention?
- Is it accessible? Can everyone use it regardless of ability?
- Is it adaptive? Does it work across all screen sizes and devices?
- Is it delightful? Does it create a positive emotional response?
Signature Material Moves
- Dynamic Color: Personalized themes from user content
- Tonal Palettes: Harmonious color derived from single source
- State Layers: Consistent interaction feedback via overlays
- Container Transform: Seamless element-to-screen transitions
- Elevation Hierarchy: Shadows that communicate importance
- Adaptive Scaffolds: Navigation that transforms with screen size
- Typography Scale: 15 styles for clear content hierarchy
- Shape System: Corners that communicate component personality