Navigation Drawer
A Material Design navigation drawer.
<md-gb-nav-drawer open aria-label="Mail">
<h2 slot="headline">Mail</h2>
<md-gb-nav-drawer-item href="#inbox" selected badge="24">
<md-gb-icon slot="icon">inbox</md-gb-icon>
Inbox
</md-gb-nav-drawer-item>
<md-gb-nav-drawer-item href="#sent">
<md-gb-icon slot="icon">send</md-gb-icon>
Sent
</md-gb-nav-drawer-item>
</md-gb-nav-drawer>Install with shadcn/ui: npx shadcn@latest add https://material-web.dev/3.0/r/md-nav-drawer.json (setup)
Usage guidelines
Link to “Usage guidelines”- Use it for top-level destinations. A drawer lists the main sections of an app, with the current one selected.
- Choose standard or modal. A standard drawer (above) sits beside the content on large windows; a modal drawer opens over a scrim on small ones.
- Group with labels. Use section labels and dividers to organize long lists.
- Keep labels short. Long labels truncate.
This component is new in M3 Expressive.
Anatomy
Link to “Anatomy”A drawer holds an optional headline, section labels, dividers, and items.
<md-gb-nav-drawer open aria-label="Mail">
<h2 slot="headline">Mail</h2>
<h2 class="nav-drawer-section-label">Folders</h2>
<md-gb-nav-drawer-item href="#anatomy-inbox" selected>
<md-gb-icon slot="icon">inbox</md-gb-icon>
<span slot="badge">24</span>
Inbox
</md-gb-nav-drawer-item>
<md-gb-nav-drawer-item href="#anatomy-drafts">
<md-gb-icon slot="icon">draft</md-gb-icon>
Drafts
</md-gb-nav-drawer-item>
<md-gb-divider></md-gb-divider>
<md-gb-nav-drawer-item href="#anatomy-trash">
<md-gb-icon slot="icon">delete</md-gb-icon>
Trash
</md-gb-nav-drawer-item>
</md-gb-nav-drawer>Examples
Link to “Examples”Modal drawer
Link to “Modal drawer”Set modal to open the drawer over a scrim. Escape, the scrim, or swiping closes it.
<md-gb-button id="open-menu">Menu</md-gb-button>
<md-gb-nav-drawer id="menu" modal aria-label="Mail">
<md-gb-nav-drawer-item href="#inbox" selected>Inbox</md-gb-nav-drawer-item>
<md-gb-nav-drawer-item href="#sent">Sent</md-gb-nav-drawer-item>
</md-gb-nav-drawer>document.querySelector('#open-menu').addEventListener('click', () => {
document.querySelector('#menu').show();
});Modal drawer without swipe
Link to “Modal drawer without swipe”Set gestures-disabled on a modal drawer to turn off swipe-to-close. Escape, the scrim, and close() still work.
<md-gb-button id="open-fixed-menu">Menu</md-gb-button>
<md-gb-nav-drawer id="fixed-menu" modal gestures-disabled aria-label="Mail">
<md-gb-nav-drawer-item href="#inbox" selected>Inbox</md-gb-nav-drawer-item>
<md-gb-nav-drawer-item href="#sent">Sent</md-gb-nav-drawer-item>
</md-gb-nav-drawer>document.querySelector('#open-fixed-menu').addEventListener('click', () => {
document.querySelector('#fixed-menu').show();
});Text labels only
Link to “Text labels only”Items work without icons. Labels that are too long truncate, and disabled items are not interactive.
<md-gb-nav-drawer open aria-label="Settings">
<md-gb-nav-drawer-item href="#general" selected>General</md-gb-nav-drawer-item>
<md-gb-nav-drawer-item href="#privacy">Privacy</md-gb-nav-drawer-item>
<md-gb-nav-drawer-item disabled>Billing</md-gb-nav-drawer-item>
</md-gb-nav-drawer>Accessibility
Link to “Accessibility”- The drawer renders a
<nav>landmark; give it a name witharia-label. - The selected item is the current page and is exposed with
aria-current. - A modal drawer is a dialog: it traps focus, closes with Escape, and returns focus to what opened it.
- Tab moves through the items; Enter activates a link item.
Compatibility
Link to “Compatibility”Material Design 30 uncovered67% tokens
142 of 256 buildable spec units are tested, 5 are excluded with a written reason and 0 are uncovered (the target is 0). 38 of 57 token declarations match the spec (67%), 1 differ on purpose or are being fixed, and 18 have no spec token.
navigation-drawer on m3.material.io (opens in a new tab) How compliance is measured
BaselineWidely availableChrome 124Edge 124Firefox 125Safari 17.4
The component’s own CSS and JavaScript rely only on web platform features that are Baseline widely available: it works in Chrome 124, Edge 124, Firefox 125, Safari 17.4 and later.
Newer features it uses where the browser has them (progressive enhancements):
- Cursor styles (opens in a new tab) Limited availability degrades safely where it is missing
- overscroll-behavior (opens in a new tab) Limited availability degrades safely where it is missing
- scrollbar-color (opens in a new tab) Newly available degrades safely where it is missing
- scrollbar-gutter (opens in a new tab) Newly available degrades safely where it is missing
- scrollbar-width (opens in a new tab) Newly available degrades safely where it is missing
- user-select (opens in a new tab) Limited availability used inside an
@supportsguard
Browser support Learn more about Baseline (opens in a new tab)
WAI-ARIAaxe and ARIA 1.3 passButtonDialog (Modal)
Roles the component renders: button (opens in a new tab), dialog (opens in a new tab), link (opens in a new tab), separator (opens in a new tab).
Follows the WAI-ARIA Authoring Practices: Button (opens in a new tab), Dialog (Modal) (opens in a new tab), Link (opens in a new tab).
3 rendered states run through axe-core and the WAI-ARIA 1.3 role and attribute rules in a real browser, with no known gaps.
WAI-ARIA 1.3 (opens in a new tab) ARIA Authoring Practices (opens in a new tab) Accessibility
Lighthouse97 · 100 · 100 · 100
Performance Accessibility Best practices SEO
Audits under 90:
- Eliminate render-blocking resources
- Minify JavaScript
- Enable text compression
- Network dependency tree
- Render blocking requests
Lighthouse 12.8.2 (desktop, 2026-11-08) on the component alone: its first example on a page of its own, without this site's shell. The modules are the development build (not bundled or minified), so the performance score is indicative.
API reference
Link to “API reference”<md-gb-nav-drawer>
Link to “<md-gb-nav-drawer>”A Material Design navigation drawer custom element.
Properties
Link to “Properties”| Property | Attribute | Type | Default |
|---|---|---|---|
gesturesDisabledWhether swiping a modal drawer closed is turned off (Compose gesturesEnabled = false). Escape, the scrim and close() still close it. |
gestures-disabled |
boolean |
false |
labelThe accessible name of the navigation landmark. Use it instead of aria-label when the host sits outside any landmark: the host's aria-label moves to a data attribute that checkers (axe region) still read as a name on a host that has no landmark role. |
label |
string |
'' |
modalWhether the drawer is modal: it opens over a scrim that blocks the rest of the app, instead of sitting next to the content. |
modal |
boolean |
false |
openWhether the drawer is open. |
open |
boolean |
|
quickWhether to skip the open and close transitions. |
quick |
boolean |
false |
Slots
Link to “Slots”| Slot | Description |
|---|---|
| default | Navigation items (md-gb-nav-drawer-item), section labels (headings or .nav-drawer-section-label) and dividers (md-gb-divider or <hr>). |
headline |
Optional headline shown above the items. |
Events
Link to “Events”| Event | Description |
|---|---|
changeEvent |
Fired when the user selects a different item. |
closeCustomEvent<{reason: string}> |
Fired when the drawer starts closing. |
closedCustomEvent<{reason: string}> |
Fired when the drawer has closed and finished animating. |
openEvent |
Fired when the drawer starts opening. |
openedEvent |
Fired when the drawer has opened and finished animating. |
Methods
Link to “Methods”| Method | Description |
|---|---|
close(reason?: string) => Promise<void> |
Closes the drawer. Resolves once it has finished animating. |
show() => Promise<void> |
Opens the drawer. Resolves once it has finished animating. |
toggle() => Promise<void> |
Opens the drawer when closed, closes it when open. |
CSS parts
Link to “CSS parts”| Part | Description |
|---|---|
::part(dialog) |
The modal drawer's <dialog>. |
::part(drawer) |
The drawer sheet. |
::part(nav) |
The <nav> landmark. |
::part(scrim) |
The modal drawer's scrim. |
CSS custom properties
Link to “CSS custom properties”| Property | Description |
|---|---|
--active-focus-icon-color |
|
--active-focus-label-text-color |
|
--active-hover-icon-color |
|
--active-hover-label-text-color |
|
--active-icon-color |
|
--active-indicator-color |
|
--active-indicator-height |
|
--active-indicator-shape |
|
--active-indicator-width |
|
--active-label-text |
|
--active-label-text-axes |
|
--active-label-text-color |
|
--active-pressed-icon-color |
|
--active-pressed-label-text-color |
|
--container-color |
|
--container-elevation |
|
--container-height |
|
--container-padding-block |
|
--container-padding-inline |
|
--container-shape |
Radius of the end corners. |
--container-width |
|
--container-width-minimum |
|
--divider-inset |
|
--headline |
|
--headline-axes |
|
--headline-color |
|
--headline-tracking |
|
--icon-size |
|
--inactive-focus-icon-color |
|
--inactive-focus-label-text-color |
|
--inactive-hover-icon-color |
|
--inactive-hover-label-text-color |
|
--inactive-icon-color |
|
--inactive-label-text-color |
|
--inactive-pressed-icon-color |
|
--inactive-pressed-label-text-color |
|
--item-icon-label-space |
|
--item-leading-space |
|
--item-trailing-space |
|
--label-text |
|
--label-text-axes |
|
--label-text-tracking |
|
--large-badge-label |
|
--large-badge-label-axes |
|
--large-badge-label-color |
|
--large-badge-label-tracking |
|
--motion-close-duration |
|
--motion-close-easing |
|
--motion-effects-duration |
|
--motion-effects-easing |
|
--motion-open-duration |
|
--motion-open-easing |
|
--scrim-color |
|
--scrollbar-gutter |
stable reserves the scrollbar gutter, so a scrollbar that appears doesn't move the items (default auto: where scrollbars take space it would narrow the 12dp indicator padding). |
--section-label-height |
|
--section-label-leading-space |
<md-gb-nav-drawer-item>
Link to “<md-gb-nav-drawer-item>”A Material Design navigation drawer item custom element.
Properties
Link to “Properties”| Property | Attribute | Type | Default |
|---|---|---|---|
badgeTrailing badge label text, such as an unread count. Ignored when content is slotted into badge. |
badge |
string |
'' |
disabledWhether the item is disabled. |
disabled |
boolean |
false |
hrefThe URL the item links to. Renders a link ( <a>) when set. |
href |
string |
'' |
relThe link's rel attribute, when href is set. |
rel |
string |
'' |
selectedWhether the item is the selected (current) destination. |
selected |
boolean |
false |
tabStopWhether the item is in the tab order. The parent md-gb-nav-drawer manages this to provide a single tab stop with arrow key navigation. |
boolean |
true |
|
targetWhere to open the linked href, e.g. _blank. |
target |
"" |
"_blank" |
Slots
Link to “Slots”| Slot | Description |
|---|---|
| default | The item's label text. |
badge |
Trailing badge label text (overrides the badge property). |
icon |
The item's leading icon (md-gb-icon). Filled when selected. |
Methods
Link to “Methods”| Method | Description |
|---|---|
blur() => void |
MDN Reference |
focus(options?: FocusOptions) => void |
Focuses the item's link or button. |
CSS parts
Link to “CSS parts”| Part | Description |
|---|---|
::part(badge) |
The trailing badge label container. |
::part(icon) |
The icon container. |
::part(item) |
The item's link or button. |
::part(label) |
The label text container. |