Material Design CSS framework with interactive JavaScript components for building responsive web applications
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Navigation components including navigation bars, side navigation menus, breadcrumbs, and pagination for application structure and user navigation with responsive behavior and Material Design styling.
Fixed navigation bar component with responsive behavior and mobile menu support.
<!-- Basic navbar structure -->
<nav>
<div class="nav-wrapper">
<a href="#" class="brand-logo">Logo</a>
<ul id="nav-mobile" class="right hide-on-med-and-down">
<li><a href="sass.html">Sass</a></li>
<li><a href="badges.html">Components</a></li>
<li><a href="collapsible.html">JavaScript</a></li>
</ul>
</div>
</nav>
<!-- Navbar with search -->
<nav>
<div class="nav-wrapper">
<form>
<div class="input-field">
<input id="search" type="search" required>
<label class="label-icon" for="search"><i class="material-icons">search</i></label>
<i class="material-icons">close</i>
</div>
</form>
</div>
</nav>
<!-- Navbar with dropdown -->
<nav>
<div class="nav-wrapper">
<a href="#" class="brand-logo">Logo</a>
<ul class="right hide-on-med-and-down">
<li><a href="#" class="dropdown-trigger" data-target="dropdown1">Dropdown<i class="material-icons right">arrow_drop_down</i></a></li>
</ul>
</div>
</nav>
<ul id="dropdown1" class="dropdown-content">
<li><a href="#!">One</a></li>
<li><a href="#!">Two</a></li>
<li class="divider"></li>
<li><a href="#!">Three</a></li>
</ul>CSS Classes:
/* Navbar classes */
nav {
/* Main navigation container */
background-color: #ee6e73;
height: 64px;
line-height: 64px;
}
.nav-wrapper {
/* Navigation content wrapper */
position: relative;
height: 100%;
}
.brand-logo {
/* Logo/brand text */
position: absolute;
color: #fff;
display: inline-block;
font-size: 2.1rem;
padding: 0;
}
.brand-logo.center {
/* Centered logo */
left: 50%;
transform: translateX(-50%);
}
/* Navigation colors */
.nav-colored { /* Custom colored nav */ }
.nav-transparent { /* Transparent nav */ }
.nav-fixed { /* Fixed position nav */ }
.nav-extended { /* Extended height nav */ }Sliding side navigation menu with touch gestures and responsive behavior.
/**
* Side navigation component
* @param el - Sidenav element
* @param options - Configuration options
*/
class Sidenav {
constructor(el: Element, options?: SidenavOptions);
static init(els: Element | NodeList, options?: SidenavOptions): Sidenav | Sidenav[];
static getInstance(el: Element): Sidenav;
static get defaults(): SidenavOptions;
/** Open sidenav */
open(): void;
/** Close sidenav */
close(): void;
destroy(): void;
/** Current open state */
isOpen: boolean;
}
interface SidenavOptions {
/** Edge for sidenav to slide from */
edge?: 'left' | 'right'; // default: 'left'
/** Allow dragging to open/close */
draggable?: boolean; // default: true
/** Enter animation duration */
inDuration?: number; // default: 250
/** Exit animation duration */
outDuration?: number; // default: 200
/** Prevent page scrolling when open */
preventScrolling?: boolean; // default: true
/** Callbacks */
onOpenStart?: () => void;
onOpenEnd?: () => void;
onCloseStart?: () => void;
onCloseEnd?: () => void;
}Usage Examples:
<!-- Sidenav structure -->
<ul id="slide-out" class="sidenav">
<li><div class="user-view">
<div class="background">
<img src="images/office.jpg">
</div>
<a href="#user"><img class="circle" src="images/yuna.jpg"></a>
<a href="#name"><span class="white-text name">John Doe</span></a>
<a href="#email"><span class="white-text email">jdandturk@gmail.com</span></a>
</div></li>
<li><a href="#!"><i class="material-icons">cloud</i>First Link With Icon</a></li>
<li><a href="#!">Second Link</a></li>
<li><div class="divider"></div></li>
<li><a class="subheader">Subheader</a></li>
<li><a class="waves-effect" href="#!">Third Link With Waves</a></li>
</ul>
<!-- Sidenav trigger -->
<a href="#" data-target="slide-out" class="sidenav-trigger">
<i class="material-icons">menu</i>
</a>// Initialize sidenav
const elems = document.querySelectorAll('.sidenav');
const instances = M.Sidenav.init(elems, {
edge: 'left',
draggable: true,
onOpenEnd: () => console.log('Sidenav opened')
});
// Programmatic control
const instance = M.Sidenav.getInstance(document.getElementById('slide-out'));
instance.open();Always-visible side navigation for desktop layouts.
<!-- Fixed sidenav structure -->
<ul id="slide-out" class="sidenav sidenav-fixed">
<li><a class="waves-effect" href="#!">First Link With Waves</a></li>
<li><a class="waves-effect" href="#!">Second Link With Waves</a></li>
</ul>CSS Classes:
/* Sidenav classes */
.sidenav {
/* Side navigation menu */
position: fixed;
width: 300px;
left: 0;
top: 0;
height: 100%;
background-color: #fff;
z-index: 999;
transform: translateX(-100%);
}
.sidenav-fixed {
/* Always visible sidenav */
left: 0;
transform: translateX(0);
position: fixed;
}
.sidenav-overlay {
/* Overlay background when sidenav is open */
position: fixed;
top: 0;
left: 0;
right: 0;
height: 120vh;
background-color: rgba(0,0,0,0.5);
z-index: 997;
}
/* Sidenav content classes */
.sidenav li > a {
/* Sidenav links */
color: rgba(0,0,0,0.87);
display: block;
font-size: 14px;
font-weight: 500;
height: 48px;
line-height: 48px;
padding: 0 32px;
}
.sidenav .user-view {
/* User info section */
position: relative;
padding: 32px 32px 0;
margin-bottom: 8px;
}
.sidenav .divider {
/* Divider line */
margin: 8px 0 0 0;
}
.sidenav .subheader {
/* Section headers */
color: rgba(0,0,0,0.54);
font-size: 14px;
font-weight: 500;
}Breadcrumb navigation showing current page location in site hierarchy.
<!-- Basic breadcrumbs -->
<nav>
<div class="nav-wrapper">
<div class="col s12">
<a href="#!" class="breadcrumb">First</a>
<a href="#!" class="breadcrumb">Second</a>
<a href="#!" class="breadcrumb">Third</a>
</div>
</div>
</nav>
<!-- Breadcrumbs with icons -->
<nav>
<div class="nav-wrapper">
<div class="col s12">
<a href="#!" class="breadcrumb"><i class="material-icons">home</i>Home</a>
<a href="#!" class="breadcrumb">Library</a>
<a href="#!" class="breadcrumb">Data</a>
</div>
</div>
</nav>CSS Classes:
/* Breadcrumb classes */
.breadcrumb {
/* Individual breadcrumb item */
font-size: 18px;
color: rgba(255,255,255,0.7);
display: inline-block;
padding: 0 15px;
}
.breadcrumb:before {
/* Separator between breadcrumbs */
content: '\E5CC';
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 25px;
margin: 0 10px 0 8px;
color: rgba(255,255,255,0.7);
vertical-align: top;
}
.breadcrumb:first-child:before {
/* Remove separator from first breadcrumb */
display: none;
}
.breadcrumb:last-child {
/* Active/current breadcrumb */
color: #fff;
}Pagination component for navigating through multiple pages of content.
<!-- Basic pagination -->
<ul class="pagination">
<li class="disabled"><a href="#!"><i class="material-icons">chevron_left</i></a></li>
<li class="active"><a href="#!">1</a></li>
<li class="waves-effect"><a href="#!">2</a></li>
<li class="waves-effect"><a href="#!">3</a></li>
<li class="waves-effect"><a href="#!">4</a></li>
<li class="waves-effect"><a href="#!">5</a></li>
<li class="waves-effect"><a href="#!"><i class="material-icons">chevron_right</i></a></li>
</ul>
<!-- Pagination with large numbers -->
<ul class="pagination">
<li class="disabled"><a href="#!"><i class="material-icons">chevron_left</i></a></li>
<li class="waves-effect"><a class="grey lighten-2" href="#!">1</a></li>
<li class="waves-effect"><a href="#!">...</a></li>
<li class="waves-effect"><a href="#!">12</a></li>
<li class="active teal"><a href="#!">13</a></li>
<li class="waves-effect"><a href="#!">14</a></li>
<li class="waves-effect"><a href="#!">...</a></li>
<li class="waves-effect"><a href="#!">24</a></li>
<li class="waves-effect"><a href="#!"><i class="material-icons">chevron_right</i></a></li>
</ul>CSS Classes:
/* Pagination classes */
.pagination {
/* Pagination container */
display: flex;
padding-left: 0;
list-style: none;
border-radius: 0.25rem;
}
.pagination li {
/* Pagination item */
display: inline-block;
}
.pagination li.active {
/* Active page indicator */
background-color: #ee6e73;
}
.pagination li.disabled {
/* Disabled pagination item */
pointer-events: none;
}
.pagination li a {
/* Pagination links */
color: #444;
display: block;
font-size: 1.2rem;
font-weight: 500;
line-height: 36px;
padding: 0 12px;
text-decoration: none;
}
.pagination li.active a {
/* Active page link */
color: #fff;
}
.pagination li.disabled a {
/* Disabled page link */
color: #999;
}Helper classes and JavaScript utilities for navigation components.
// Navigation helper utilities
declare const M: {
/** Initialize all navigation components */
AutoInit(): void;
};
// Common navigation patterns
function initializeNavigation() {
// Initialize dropdowns in navbar
const dropdownElems = document.querySelectorAll('.dropdown-trigger');
M.Dropdown.init(dropdownElems);
// Initialize sidenav
const sidenavElems = document.querySelectorAll('.sidenav');
M.Sidenav.init(sidenavElems);
// Initialize collapsible in sidenav
const collapsibleElems = document.querySelectorAll('.collapsible');
M.Collapsible.init(collapsibleElems);
}<!-- Mobile-responsive navbar -->
<nav>
<div class="nav-wrapper">
<a href="#" class="brand-logo">Logo</a>
<a href="#" data-target="mobile-demo" class="sidenav-trigger">
<i class="material-icons">menu</i>
</a>
<ul class="right hide-on-med-and-down">
<li><a href="sass.html">Sass</a></li>
<li><a href="badges.html">Components</a></li>
</ul>
</div>
</nav>
<!-- Mobile sidenav -->
<ul class="sidenav" id="mobile-demo">
<li><a href="sass.html">Sass</a></li>
<li><a href="badges.html">Components</a></li>
</ul>Responsive CSS Classes:
/* Responsive navigation utilities */
.hide-on-small-only { /* Hide on small screens only */ }
.hide-on-med-and-down { /* Hide on medium and small screens */ }
.hide-on-med-and-up { /* Hide on medium and large screens */ }
.hide-on-med-only { /* Hide on medium screens only */ }
.hide-on-large-only { /* Hide on large screens only */ }
.show-on-small { /* Show on small screens only */ }
.show-on-medium { /* Show on medium screens only */ }
.show-on-large { /* Show on large screens only */ }
.show-on-medium-and-up { /* Show on medium and large screens */ }
.show-on-medium-and-down { /* Show on medium and small screens */ }
.sidenav-trigger {
/* Mobile menu trigger button */
display: none;
}
@media only screen and (max-width: 992px) {
.sidenav-trigger {
display: block;
}
}<!-- Navbar with nested dropdowns -->
<nav>
<div class="nav-wrapper">
<ul class="left">
<li>
<a class="dropdown-trigger" href="#!" data-target="dropdown1">
Categories<i class="material-icons right">arrow_drop_down</i>
</a>
</li>
</ul>
</div>
</nav>
<ul id="dropdown1" class="dropdown-content">
<li><a href="#!">Web Design</a></li>
<li><a href="#!">Web Development</a></li>
<li class="divider"></li>
<li><a href="#!">Mobile Apps</a></li>
</ul>/* Sticky navigation */
.navbar-fixed {
position: relative;
height: 56px;
z-index: 997;
}
.navbar-fixed nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 998;
}<!-- Expandable search in navbar -->
<nav>
<div class="nav-wrapper">
<form>
<div class="input-field">
<input id="search" type="search" required>
<label class="label-icon" for="search">
<i class="material-icons">search</i>
</label>
<i class="material-icons">close</i>
</div>
</form>
</div>
</nav>ScrollSpy component for automatically highlighting navigation items based on scroll position, ideal for table of contents, section navigation, and single-page applications.
/**
* ScrollSpy component for scroll-based navigation highlighting
* @param el - Element to track (usually content sections with IDs)
* @param options - Configuration options
*/
class ScrollSpy {
constructor(el: Element, options?: ScrollSpyOptions);
/** Initialize scrollspy instances */
static init(els: Element | NodeList, options?: ScrollSpyOptions): ScrollSpy | ScrollSpy[];
/** Get existing scrollspy instance */
static getInstance(el: Element): ScrollSpy;
/** Get default options */
static get defaults(): ScrollSpyOptions;
/** Destroy scrollspy instance */
destroy(): void;
/** ScrollSpy element */
el: Element;
/** Configuration options */
options: ScrollSpyOptions;
/** Unique instance ID */
id: number;
/** Current tick ID for tracking */
tickId: number;
}
interface ScrollSpyOptions {
/** Throttle delay for scroll events (ms) */
throttle?: number; // default: 100
/** Offset from viewport top for activation */
scrollOffset?: number; // default: 200
/** CSS class applied to active navigation elements */
activeClass?: string; // default: 'active'
/** Function to find navigation element for given section ID */
getActiveElement?: (id: string) => string; // default: 'a[href="#' + id + '"]'
}Usage Examples:
<!-- Content sections with IDs -->
<section id="introduction" class="scrollspy">
<h2>Introduction</h2>
<p>Content for introduction section...</p>
</section>
<section id="features" class="scrollspy">
<h2>Features</h2>
<p>Content for features section...</p>
</section>
<section id="installation" class="scrollspy">
<h2>Installation</h2>
<p>Content for installation section...</p>
</section>
<!-- Navigation that will be highlighted -->
<ul class="section-nav">
<li><a href="#introduction">Introduction</a></li>
<li><a href="#features">Features</a></li>
<li><a href="#installation">Installation</a></li>
</ul>// Initialize scrollspy
const elems = document.querySelectorAll('.scrollspy');
const instances = M.ScrollSpy.init(elems, {
scrollOffset: 100,
throttle: 50,
activeClass: 'current'
});
// Custom active element selector
M.ScrollSpy.init(elems, {
scrollOffset: 150,
getActiveElement: function(id) {
return `.nav-item[data-target="${id}"]`;
}
});
// Table of contents scrollspy
const sections = document.querySelectorAll('h2[id]');
M.ScrollSpy.init(sections, {
scrollOffset: 50,
activeClass: 'highlighted'
});Features:
<!-- Tab-style navigation -->
<div class="row">
<div class="col s12">
<ul class="tabs">
<li class="tab col s3"><a href="#test1">Test 1</a></li>
<li class="tab col s3"><a class="active" href="#test2">Test 2</a></li>
<li class="tab col s3"><a href="#test3">Test 3</a></li>
<li class="tab col s3"><a href="#test4">Test 4</a></li>
</ul>
</div>
</div>