This is a slide-out menu. Nest <details> /
<summary> for nested sections — the
documentation sidebar uses that. On Compact and Medium windows this same
drawer slides over the page.
An overlay sidenav is a modal <dialog>.
The framework wraps your <ul class="navigation-drawer">;
Escape and a tap on the backdrop close it.
A navigation-drawer-fixed drawer stays open from Expanded as CSS —
no resize listener, no overlay.
The sidenav HTML must not sit inside the app bar’s
<nav>.
Put a navigation-drawer-trigger anywhere and set data-target to the navigation drawer’s
id. AutoInit() starts every .navigation-drawer except those marked
no-autoinit.
<nav aria-label="Main">
<ul id="slide-out" class="navigation-drawer">
<li>
<div class="user-view">
<div class="background">
<img src="images/office.jpg" alt="">
</div>
<a href="#user" aria-label="Profile"><img class="circle" src="images/portrait.jpg" alt=""></a>
<a href="#name"><span class="name">John Doe</span></a>
<a href="#email"><span class="email">jdoe@example.com</span></a>
</div>
</li>
<li><a href="#!"><span class="material-symbols" aria-hidden="true">cloud</span>First Link With Icon</a></li>
<li><a href="#!">Second Link</a></li>
<li><div class="divider"></div></li>
<li><span class="subheader">Subheader</span></li>
<li><a href="#!">Third Link</a></li>
</ul>
</nav>
<button type="button" data-target="slide-out" class="button text circle navigation-drawer-trigger" aria-label="Menu"><span class="material-symbols" aria-hidden="true">menu</span></button>
Initialization
The IIFE bundle exposes Expressive.NavigationDrawer.
Call init yourself when you need options other than the defaults,
or let Expressive.AutoInit() start every .navigation-drawer.
document.addEventListener('DOMContentLoaded', function() {
const elems = document.querySelectorAll('.navigation-drawer');
const instances = Expressive.NavigationDrawer.init(elems, {
// specify options here
});
});
Options
| Name | Type | Default | Description |
|---|---|---|---|
edge |
String | 'left' |
Side of the screen. 'left' or 'right'. The constructor adds right-aligned when the edge is right. |
draggable |
Boolean | true |
Allow swipe gestures to open and close. Drag is disabled while the navigation drawer is fixed on Expanded and wider windows. |
dragTargetWidth |
String | '10px' |
Width of the screen-edge strip where a drag can start. |
onOpenStart |
Function | null |
Called when the navigation drawer starts opening. |
onOpenEnd |
Function | null |
Called when the navigation drawer finishes opening. |
onCloseStart |
Function | null |
Called when the navigation drawer starts closing. |
onCloseEnd |
Function | null |
Called when the navigation drawer finishes closing. |
Methods
All methods are called on the plugin instance. You can get the instance like this:
const instance = Expressive.NavigationDrawer.getInstance(elem);
.open();
Opens the navigation drawer.
instance.open();
.close();
Closes the navigation drawer.
instance.close();
.destroy();
Destroy the plugin instance, unwrap the dialog host, and remove the drag target and event handlers.
instance.destroy();
Properties
| Name | Type | Description |
|---|---|---|
el |
Element | The DOM element the plugin was initialized with. |
options |
Object | The options the instance was initialized with. |
isOpen |
Boolean | Whether the overlay drawer is open. Stays false while a fixed sidenav is docked on Expanded and wider windows. |
isFixed |
Boolean | Whether the element has navigation-drawer-fixed. |
isDragged |
Boolean | Whether the navigation drawer is being dragged. |
Close Trigger
Add navigation-drawer-close to an element inside the navigation drawer. A click on that element
closes an overlay sidenav. That is useful in a single-page app where the page does not
reload. It does nothing while the navigation drawer is fixed on Expanded and wider windows.
<nav aria-label="Main">
<ul id="slide-out" class="navigation-drawer">
<li><button type="button" class="navigation-drawer-close">Clicking this will close NavigationDrawer</button></li>
</ul>
</nav>
<button type="button" data-target="slide-out" class="button text circle navigation-drawer-trigger" aria-label="Menu"><span class="material-symbols" aria-hidden="true">menu</span></button>
Variations
Right edge
Pass edge: 'right'. Mark the element no-autoinit if you initialize it
yourself, otherwise AutoInit would start it on the left.
Expressive.NavigationDrawer.init(document.querySelector('#slide-out-right'), {
edge: 'right'
});
Nested sections
Nest <details> for a section that opens in
place. Same name on several details is an
accordion. The documentation sidebar uses this for Foundations,
Structure, Components, and Forms.
<nav aria-label="Main">
<ul id="slide-out" class="navigation-drawer">
<li><a href="#!">First Sidebar Link</a></li>
<li>
<details name="docs-nav">
<summary>
<span class="material-symbols" aria-hidden="true">palette</span>
Foundations
</summary>
<ul>
<li><a href="#!">Color</a></li>
<li><a href="#!">Typography</a></li>
</ul>
</details>
</li>
</ul>
</nav>
Fixed HTML Structure
Add navigation-drawer-fixed so the navigation drawer stays open from Expanded (840px and up)
and slides away on smaller ones. That dock is CSS, not a JavaScript open().
The documentation sidebar on the left is this pattern.
<nav aria-label="Main">
<ul id="slide-out" class="navigation-drawer navigation-drawer-fixed">
<li><a href="#!">First Sidebar Link</a></li>
<li><a href="#!">Second Sidebar Link</a></li>
</ul>
</nav>
<button type="button" data-target="slide-out" class="button text circle navigation-drawer-trigger" aria-label="Menu"><span class="material-symbols" aria-hidden="true">menu</span></button>
Offset the rest of the page by the navigation drawer width. The width token is
--md-comp-nav-drawer-width (alias of --md-comp-nav-drawer-width, 300px).
Put the padding on header, main, and footer.
@media (width >= 840px) {
header, main, footer {
padding-left: var(--md-comp-nav-drawer-width);
}
}