Material Design Components in CSS, JS and HTML providing a comprehensive implementation of Google's Material Design specification for web applications.
npx @tessl/cli install tessl/npm-material-design-lite@1.3.0Material Design Lite (MDL) is a comprehensive JavaScript UI component library that implements Google's Material Design specification using vanilla CSS, JavaScript, and HTML. It enables developers to add Material Design styling and interactive components to static websites without requiring JavaScript frameworks or libraries, offering cross-device compatibility and graceful degradation for older browsers.
npm install material-design-lite<!-- CSS -->
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.indigo-pink.min.css">
<!-- JavaScript -->
<script defer src="https://code.getmdl.io/1.3.0/material.min.js"></script>Material Design Lite is primarily designed for browser use. When used in Node.js environments (like server-side rendering), only the global componentHandler is available:
// Access componentHandler in Node.js environment
require('material-design-lite');
// componentHandler is now available as a globalNote: Individual component classes (MaterialButton, MaterialTextfield, etc.) are not exported as CommonJS modules and are only available in browser environments after the library is loaded.
<!-- Include built files -->
<link rel="stylesheet" href="path/to/material.min.css">
<script src="path/to/material.min.js"></script>
<!-- Access global componentHandler -->
<script>
// componentHandler is available globally
componentHandler.upgradeAllRegistered();
</script>Material Design Lite works by applying CSS classes to HTML elements and then upgrading them with JavaScript functionality.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.indigo-pink.min.css">
</head>
<body>
<!-- Button with ripple effect -->
<button class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect">
Click Me
</button>
<!-- Text field with floating label -->
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" id="sample3">
<label class="mdl-textfield__label" for="sample3">Text...</label>
</div>
<!-- Menu -->
<button id="demo-menu-lower-left"
class="mdl-button mdl-js-button mdl-button--icon">
<i class="material-icons">more_vert</i>
</button>
<ul class="mdl-menu mdl-menu--bottom-left mdl-js-menu mdl-js-ripple-effect"
for="demo-menu-lower-left">
<li class="mdl-menu__item">Some Action</li>
<li class="mdl-menu__item">Another Action</li>
</ul>
<script defer src="https://code.getmdl.io/1.3.0/material.min.js"></script>
</body>
</html>Material Design Lite is built around several key architectural concepts:
Core system for managing component lifecycle, registration, and upgrades. Essential for dynamic content and programmatic control.
interface ComponentHandler {
/** Upgrade all elements with MDL components in the DOM */
upgradeDom(optJsClass?: string, optCssClass?: string): void;
/** Upgrade a specific element with MDL components */
upgradeElement(element: Element, optJsClass?: string): void;
/** Upgrade a list of elements with MDL components */
upgradeElements(elements: Element[] | NodeList | HTMLCollection): void;
/** Upgrade all registered components in the DOM */
upgradeAllRegistered(): void;
/** Register a callback for component upgrades */
registerUpgradedCallback(jsClass: string, callback: (element: HTMLElement) => void): void;
/** Register a new component type */
register(config: ComponentConfigPublic): void;
/** Downgrade components on specified elements */
downgradeElements(nodes: Node[] | NodeList): void;
}
interface ComponentConfigPublic {
constructor: Function;
classAsString: string;
cssClass: string;
widget?: boolean;
}Interactive form controls including buttons, text fields, checkboxes, radio buttons, switches, and sliders with Material Design styling and behavior.
interface MaterialButton {
/** Disable the button */
disable(): void;
/** Enable the button */
enable(): void;
}
interface MaterialTextfield {
/** Check and update disabled state */
checkDisabled(): void;
/** Check and update focus state */
checkFocus(): void;
/** Check and update validity state */
checkValidity(): void;
/** Disable the textfield */
disable(): void;
/** Enable the textfield */
enable(): void;
/** Update textfield value */
change(value: string): void;
}
interface MaterialCheckbox {
/** Disable the checkbox */
disable(): void;
/** Enable the checkbox */
enable(): void;
/** Check the checkbox */
check(): void;
/** Uncheck the checkbox */
uncheck(): void;
}Structural components for application layout including headers, drawers, navigation, tabs, and responsive grid systems.
interface MaterialLayout {
/** Toggle drawer open/closed state */
toggleDrawer(): void;
}
interface MaterialLayoutTab {
/** Programmatically select this tab */
show(): void;
}Menu systems and navigation components including dropdown menus, tabs, and navigation drawers.
interface MaterialMenu {
/** Display the menu */
show(evt?: Event): void;
/** Hide the menu */
hide(): void;
/** Toggle menu visibility */
toggle(evt?: Event): void;
}User feedback components including progress indicators, spinners, snackbars, and tooltips for communicating system state and user actions.
interface MaterialSnackbar {
/** Show snackbar with configuration */
showSnackbar(data: SnackbarData): void;
}
interface SnackbarData {
/** Text message to display */
message: string;
/** Optional action button text */
actionText?: string;
/** Optional action click handler */
actionHandler?: () => void;
/** Optional timeout in milliseconds (default: 2750) */
timeout?: number;
}
interface MaterialProgress {
/** Set progress value (0-100) */
setProgress(value: number): void;
/** Set buffer value (0-100) */
setBuffer(value: number): void;
}Components for displaying structured data including data tables with sorting and selection capabilities.
// MaterialDataTable provides automatic functionality for data tables
// No programmatic API - behavior is entirely declarative via HTML/CSSVisual enhancement components including ripple effects and animations that provide tactile feedback and smooth transitions.
interface MaterialRipple {
/** Get animation frame count */
getFrameCount(): number;
/** Set animation frame count */
setFrameCount(frameCount: number): void;
/** Get ripple element */
getRippleElement(): HTMLElement;
/** Set ripple coordinates */
setRippleXY(x: number, y: number): void;
/** Set ripple styling */
setRippleStyles(start: boolean): void;
/** Handle animation frames */
animFrameHandler(): void;
}// Events
interface MDLComponentUpgradingEvent extends CustomEvent {
type: 'mdl-componentupgrading';
bubbles: true;
cancelable: true;
}
interface MDLComponentUpgradedEvent extends CustomEvent {
type: 'mdl-componentupgraded';
bubbles: true;
cancelable: false;
}
interface MDLComponentDowngradedEvent extends CustomEvent {
type: 'mdl-componentdowngraded';
bubbles: true;
cancelable: false;
}
// Component Configuration
interface ComponentConfig {
constructor: Function;
className: string;
cssClass: string;
widget: boolean;
callbacks: Array<(element: HTMLElement) => void>;
}
// Component Instance
interface Component {
element_: HTMLElement;
className: string;
classAsString: string;
cssClass: string;
widget: string;
}Widget Components (widget: true):
// Access component instance via element property
const button = document.querySelector('.mdl-js-button');
button.MaterialButton.disable();
const textfield = document.querySelector('.mdl-js-textfield');
textfield.MaterialTextfield.change('new value');Non-Widget Components (widget: false):
// No direct instance access - behavior is automatic
// Use componentHandler for lifecycle management only
componentHandler.upgradeElement(newElement);// When adding MDL components dynamically
const newButton = document.createElement('button');
newButton.className = 'mdl-button mdl-js-button mdl-button--raised';
newButton.textContent = 'Dynamic Button';
document.body.appendChild(newButton);
// Upgrade the new element
componentHandler.upgradeElement(newButton);
// Or upgrade multiple elements
componentHandler.upgradeElements([newButton, anotherElement]);try {
componentHandler.upgradeElement(invalidElement);
} catch (error) {
// Handle upgrade errors
console.error('Failed to upgrade element:', error);
}
// Listen for upgrade events
element.addEventListener('mdl-componentupgrading', (event) => {
// Cancel upgrade if needed
event.preventDefault();
});classList, querySelector, addEventListener, Array.prototype.forEachmdl-js class to <html> when supported