Sidenav

Materialize is a modern responsive CSS framework based on Material Design by Google.

Workspace navigation rail

An always-visible 88px rail for workspace navigation. Square icon buttons are grouped by production area; hover or focus a button for its label.

Production workspace

Home

Your production workspace: quick access to the tools you use every day.

One workspace, every department.

Choose a tool from the navigation to preview its destination.

Home selected.

Markup — Crazy buttons and navigation groups
<div class="workspace-nav-preview" data-layout="rail">
<nav class="workspace-demo-navigation" aria-label="Production navigation">
  <div class="workspace-demo-group" role="group" aria-label="Workspace">
    <crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="1" icon-text="home" label="Home" data-redirect-name="Home" color-primary="gold" color-secondary="#211b00" aria-current="page"></crazy-button>
    <crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="flat" icon-text="schedule" label="Timelog" data-redirect-name="Timelog" color-secondary="var(--md-sys-color-primary)"></crazy-button>
  </div>
  <div class="workspace-demo-group" role="group" aria-label="Out.">
    <span>Out.</span>
    <crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="1" icon-text="social_distance" label="Outsource Turnover" data-redirect-name="OutsourceTurnover" color-primary="#4fc3f7" color-secondary="#052e3c"></crazy-button>
    <crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="1" icon-text="microwave" label="Brief Outsource" data-redirect-name="OutsourceBrief" color-primary="#26a69a" color-secondary="#002e29"></crazy-button>
  </div>
  <div class="workspace-demo-group" role="group" aria-label="Prod.">
    <span>Prod.</span>
    <crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="1" icon-text="schedule" label="Timelog Summary" data-redirect-name="TimelogSummary" color-primary="#ab47bc" color-secondary="#fff"></crazy-button>
  </div>
  <div class="workspace-demo-group" role="group" aria-label="Studio">
    <span>Studio</span>
    <crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="1" icon-text="stadium" label="Studio Resource" data-redirect-name="StudioResource" color-primary="#ec407a" color-secondary="#fff"></crazy-button>
    <crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="1" icon-text="view_timeline" label="Crew Planning" data-redirect-name="Planning" color-primary="#ef6c00" color-secondary="#fff"></crazy-button>
  </div>
  <div class="workspace-demo-group" role="group" aria-label="Admin">
    <span>Admin</span>
    <crazy-button tooltip-position="right" type="floating" size="large" shape="box" depth="flat" icon-text="settings" label="Settings" data-redirect-name="Settings" color-secondary="var(--md-sys-color-on-surface)"></crazy-button>
  </div>
</nav>
  <div class="workspace-demo-content">
    <p class="workspace-demo-eyebrow">Production workspace</p>
    <h4 data-workspace-title>Home</h4>
    <p class="workspace-demo-description" data-workspace-description>Your production workspace: quick access to the tools you use every day.</p>
    <div class="workspace-demo-detail"><strong>One workspace, every department.</strong><p>Choose a tool from the navigation to preview its destination.</p></div>
    <p data-crazy-button-status role="status">Home selected.</p>
  </div>
</div>

The section colors follow the reference; the surrounding surfaces follow the environment theme. data-redirect-name retains the original route identifiers. These examples update the preview; connect buttonaction to your application router for real navigation. Preview layout styles are shown below.

Preview layout CSS
// Documentation preview layout; all controls are kmaterialize CrazyButton instances.
.workspace-nav-preview {
  border: 1px solid var(--md-sys-color-outline-variant);
  border-radius: 20px;
  overflow: hidden;
  background: var(--md-sys-color-surface);
  color: var(--md-sys-color-on-surface);
  margin: 24px 0;
  .workspace-demo-navigation {
    background: var(--md-sys-color-surface-container, var(--md-sys-color-surface-variant));
    box-shadow: none;
    color: var(--md-sys-color-on-surface-variant);
    height: auto;
    line-height: normal;
  }
  .workspace-demo-group { display: flex; align-items: center; gap: 12px; }
  .workspace-demo-group > span { font-size: 11px; font-weight: 600; letter-spacing: .04em; }
  crazy-button { flex-shrink: 0; }
  crazy-button[aria-current='page'] { outline: 2px solid var(--md-sys-color-primary); outline-offset: 4px; border-radius: 16px; }
  .workspace-demo-content { min-width: 0; padding: clamp(16px, 4vw, 32px); }
  .workspace-demo-eyebrow { margin: 0 0 12px; font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--md-sys-color-on-surface-variant); }
  h4 { font-size: clamp(22px, 3vw, 32px); margin: 0 0 12px; }
  .workspace-demo-description { font-size: 14px; line-height: 1.6; }
  .workspace-demo-detail { margin-top: 24px; padding: 16px; border-radius: 12px; background: var(--md-sys-color-surface-variant); font-size: 13px; }
  &[data-layout='rail'] {
    display: grid;
    grid-template-columns: 88px minmax(0, 1fr);
    .workspace-demo-navigation { display: flex; flex-direction: column; align-items: center; gap: 24px; padding: 20px 0; }
    .workspace-demo-group { flex-direction: column; }
    .workspace-demo-content { border-left: 1px solid var(--md-sys-color-outline-variant); }
  }
  &[data-layout='toolbar'] {
    .toolbar { margin: 0; border-radius: 0; padding: 16px; gap: 24px; }
    .workspace-demo-group > span { writing-mode: vertical-rl; transform: rotate(180deg); }
  }
}

1. Slide-out drawer

This is a slide out menu. You can add a dropdown to your sidebar by using our collapsible component. If you want to see a demo, our sidebar will use this on smaller screens. To use this in conjunction with a fullscreen navigation, you have to use two copies of the same UL.

Please note that the sidenav HTML should not be contained within the navbar HTML.

Toggle Sidenav
<nav><!-- navbar content here  --></nav>
<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">jdoe@example.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>
<a href="#" data-target="slide-out" class="sidenav-trigger">
  <i class="material-icons">menu</i>
</a>

2. Documentation drawer

A second variant matching this site's drawer: Kmaterialize branding, a search field, expandable sections, and an active page. This sample includes representative links from the docs menu.

Open documentation drawer in a full window

The preview docks the drawer at 560px and above; below that, the menu button opens it as an overlay. Use 993px instead to match the main site's desktop breakpoint. Search uses the same autocomplete and full page index as the website. Select a suggestion to open the page. In your own app, replace the imported config.pages with your route list. Links navigate to actual documentation pages. This example reads the same saved theme and palette as the site, using @material/material-color-utilities.

HTML — structure and navigation
<body class="drawer-example">
  <!-- Drawer: logo, search, and grouped page links. Keep it outside the navbar. -->
  <ul id="docs-example-menu" class="sidenav" aria-label="Documentation">
    <li class="drawer-example-brand">
      <a href="index.html" target="_top">
        <img src="images/materialize.svg" alt="" />
        Kmaterialize
      </a>
    </li>
    <!-- Autocomplete uses the full documentation page index. -->
    <li class="drawer-example-search">
      <div class="input-field outlined">
        <input
          id="docs-example-search"
          class="search-docs"
          type="text"
          placeholder=" "
          autocomplete="off"
        />
        <label for="docs-example-search">Search</label>
      </div>
    </li>
    <li>
      <a href="about.html" target="_top">
        <i class="material-icons" aria-hidden="true">info</i>
        About
      </a>
    </li>
    <li>
      <a href="getting-started.html" target="_top">
        <i class="material-icons" aria-hidden="true">apps</i>
        Getting started
      </a>
    </li>
    <!-- Expandable navigation groups. The active section starts open. -->
    <li>
      <ul class="collapsible collapsible-accordion">
        <li>
          <button type="button" class="collapsible-header">
            <i class="material-icons" aria-hidden="true">palette</i>
            Styles
          </button>
          <div class="collapsible-body">
            <ul>
              <li><a href="color.html" target="_top">Color</a></li>
              <li><a href="grid.html" target="_top">Grid</a></li>
              <li><a href="themes.html" target="_top">Themes</a></li>
              <li><a href="typography.html" target="_top">Typography</a></li>
            </ul>
          </div>
        </li>
        <li class="active">
          <button type="button" class="collapsible-header">
            <i class="material-icons" aria-hidden="true">add_circle</i>
            Components
          </button>
          <div class="collapsible-body">
            <ul>
              <li><a href="cards.html" target="_top">Cards</a></li>
              <li><a href="kanban.html" target="_top">Kanban</a></li>
              <li><a href="navbar.html" target="_top">Navbar</a></li>
              <li><a href="org-chart.html" target="_top">Org Chart</a></li>
              <li class="active">
                <a href="sidenav.html" target="_top" aria-current="page">Sidenav</a>
              </li>
              <li><a href="tabs.html" target="_top">Tabs</a></li>
            </ul>
          </div>
        </li>
        <li>
          <button type="button" class="collapsible-header">
            <i class="material-icons" aria-hidden="true">text_fields</i>
            Forms
          </button>
          <div class="collapsible-body">
            <ul>
              <li><a href="autocomplete.html" target="_top">Autocomplete</a></li>
              <li><a href="checkboxes.html" target="_top">Checkboxes</a></li>
              <li><a href="select.html" target="_top">Select</a></li>
            </ul>
          </div>
        </li>
      </ul>
    </li>
    <li>
      <a href="mobile.html" target="_top">
        <i class="material-icons" aria-hidden="true">mobile_friendly</i>
        Mobile
      </a>
    </li>
  </ul>
  <!-- Page area: offset beside the drawer on wide screens. -->
  <div class="drawer-example-page">
    <nav class="navbar">
      <div class="nav-wrapper primary">
        <!-- Visible on narrow screens; JavaScript updates aria-expanded. -->
        <button
          type="button"
          id="docs-example-toggle"
          class="btn text"
          aria-controls="docs-example-menu"
          aria-expanded="false"
          aria-label="Open navigation"
        >
          <i class="material-icons" aria-hidden="true">menu</i>
        </button>
        <span>Documentation</span>
      </div>
    </nav>
    <main class="drawer-example-content">
      <span class="chip">Variant 2</span>
      <h1>
        A familiar place
        <br />
        to find your way.
      </h1>
      <p>
        The docs drawer brings search, expandable sections, and the current page
        together.
      </p>
      <p>
        Search any documentation page, or expand Styles and Forms. The links open the
        corresponding documentation pages.
      </p>
      <p class="drawer-example-note" role="status" id="docs-example-status">
        The drawer stays open on wider screens.
      </p>
    </main>
  </div>
  <!-- Load the TypeScript below through your bundler. -->
  <script type="module" src="/sidenav-docs-demo.ts"></script>
</body>
SCSS — layout, colors, and responsive styles
// Load the icon font and Materialize before these example-specific styles.
@import 'material-icons/iconfont/material-icons.css';
@import 'kmaterialize/sass/materialize.scss';

// Base surface and drawer dimensions.
.drawer-example {
  margin: 0;
  background: var(--md-sys-color-background);
  color: var(--md-sys-color-on-background);
}
.drawer-example .sidenav {
  width: 300px;
}
.drawer-example-brand > a {
  display: flex !important;
  align-items: center;
  gap: 16px;
  height: 72px !important;
  font-size: 22px !important;
}
.drawer-example-brand img {
  width: 28px;
  height: 28px;
}
// Use kmaterialize’s outlined field; only sidebar spacing is customized.
.drawer-example-search {
  margin: 8px 16px 16px;
  line-height: 1.25;
  .input-field { margin: 0; }
}
.drawer-example [hidden] {
  display: none !important;
}
.drawer-example .nav-wrapper {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 16px;
}
.drawer-example .nav-wrapper .btn {
  color: var(--md-sys-color-on-primary);
}
// Content spacing and typography for the preview.
.drawer-example-content {
  padding: 32px 24px;
}
.drawer-example-content h1 {
  font-size: clamp(28px, 4vw, 52px);
  line-height: 1.1;
  letter-spacing: -0.035em;
}
.drawer-example-content p {
  max-width: 48ch;
  line-height: 1.6;
}
.drawer-example-note {
  font-size: 13px;
  color: var(--md-sys-color-on-surface-variant);
}
// JavaScript applies this class at 560px: dock the drawer and hide the overlay.
.drawer-example-docked .drawer-example-page {
  margin-left: 300px;
}
.drawer-example-docked .sidenav-overlay,
.drawer-example-docked #docs-example-toggle {
  display: none !important;
}
TypeScript — initialization and interactions
import { Sidenav, Collapsible, Autocomplete } from 'kmaterialize';
import './sidenav-docs-demo.scss';
// This project supplies the page index. Use your own route list in another app.
import { config } from '../config.materialize';
import {
  applyTheme,
  argbFromHex,
  themeFromSourceColor,
} from '@material/material-color-utilities';

// Use the same saved palette and theme as the documentation site.
const seed = localStorage.getItem('theme-primary-color') || '#FFD700';
const preference = localStorage.getItem('theme-mode');
const dark = preference
  ? preference === 'dark'
  : matchMedia('(prefers-color-scheme: dark)').matches;
applyTheme(themeFromSourceColor(argbFromHex(seed)), {
  target: document.documentElement,
  dark,
});
document.documentElement.setAttribute('theme', dark ? 'dark' : 'light');

// Find the drawer and its controls after the HTML has loaded.
const menu = document.querySelector<HTMLElement>('#docs-example-menu')!;
const toggle = document.querySelector<HTMLButtonElement>('#docs-example-toggle')!;
const search = document.querySelector<HTMLInputElement>('#docs-example-search')!;
const wide = matchMedia('(min-width: 560px)');
// Initialize the drawer and keep the menu button state accessible.
const drawer = Sidenav.init(menu, {
  draggable: false,
  preventScrolling: false,
  onOpenStart: () => toggle.setAttribute('aria-expanded', 'true'),
  onCloseStart: () => toggle.setAttribute('aria-expanded', 'false'),
});
// Allow several navigation groups to stay open at once.
Collapsible.init(menu.querySelector<HTMLElement>('.collapsible')!, {
  accordion: false,
});
// Wide screens dock the drawer; narrow screens use the menu button.
function resize() {
  document.body.classList.toggle('drawer-example-docked', wide.matches);
  if (wide.matches) drawer.open();
  else drawer.close();
}
wide.addEventListener('change', resize);
resize();
// Toggle the mobile drawer; Escape closes it and restores button focus.
toggle.addEventListener('click', () =>
  drawer.isOpen ? drawer.close() : drawer.open(),
);
document.addEventListener('keydown', (event) => {
  if (event.key === 'Escape' && !wide.matches && drawer.isOpen) {
    drawer.close();
    toggle.focus();
  }
});
// Match the documentation site's autocomplete and complete page index.
Autocomplete.init(search, {
  minLength: 1,
  data: config.pages.map((page) => ({
    id: page.id,
    text: page.name,
    description: page.description,
    url: page.url,
  })),
  onAutocomplete: (items) => {
    if (items.length === 1) window.top!.location.href = items[0]['url'];
  },
});

3. Material 3 navigation rail

A compact rail inspired by the Material Design website: centered icons and labels, the website’s current colors, and circular motion and theme controls at the bottom. This example uses the Kmaterialize logo and Material Icons.

Open navigation rail in a full window

Choose a section to update the preview. The bottom controls pause the illustration and switch the example's light/dark theme. Its initial palette and theme match the website, and updates from the surrounding page are reflected automatically. Motion starts paused when the device requests reduced motion. The rail stays visible on phones and scrolls when the screen is too short.

The rail layout is included in kmaterialize and uses native links, so it needs no Sidenav.init(). Load Materialize and Material Icons. The SCSS below only styles the preview content. The theme control uses @material/material-color-utilities. Replace the demo hash links with your app's routes and preserve aria-current="page" on the active link.

HTML — structure and navigation
<body class="rail-example">
  <!-- Fixed rail: section links above, utility buttons below. -->
  <aside class="m3-rail" aria-label="Site navigation">
    <nav class="m3-rail-nav" aria-label="Main sections">
      <!-- Each link pairs an icon with a visible label. aria-current marks the active page. -->
      <a href="#home" aria-current="page" data-view="Home">
        <span class="m3-rail-icon"><img src="images/materialize.svg" alt="" /></span>
        <span>Home</span>
      </a>
      <a href="#get-started" data-view="Get started">
        <span class="m3-rail-icon">
          <i class="material-icons" aria-hidden="true">apps</i>
        </span>
        <span>Get started</span>
      </a>
      <a href="#develop" data-view="Develop">
        <span class="m3-rail-icon">
          <i class="material-icons" aria-hidden="true">code</i>
        </span>
        <span>Develop</span>
      </a>
      <a href="#foundations" data-view="Foundations">
        <span class="m3-rail-icon">
          <i class="material-icons" aria-hidden="true">book</i>
        </span>
        <span>Foundations</span>
      </a>
      <a href="#styles" data-view="Styles">
        <span class="m3-rail-icon">
          <i class="material-icons" aria-hidden="true">palette</i>
        </span>
        <span>Styles</span>
      </a>
      <a href="#components" data-view="Components">
        <span class="m3-rail-icon">
          <i class="material-icons" aria-hidden="true">add_circle_outline</i>
        </span>
        <span>Components</span>
      </a>
      <a href="#blog" data-view="Blog">
        <span class="m3-rail-icon">
          <i class="material-icons" aria-hidden="true">stars</i>
        </span>
        <span>Blog</span>
      </a>
    </nav>
    <!-- Bottom actions: pause motion and change the theme. -->
    <div class="m3-rail-actions">
      <button
        type="button"
        id="rail-motion"
        aria-label="Pause motion"
        aria-pressed="false"
      >
        <i class="material-icons" aria-hidden="true">pause</i>
      </button>
      <button type="button" id="rail-theme" aria-label="Switch to light theme">
        <i class="material-icons" aria-hidden="true">light_mode</i>
      </button>
    </div>
  </aside>
  <!-- Demo content. Replace hash navigation with your application routes. -->
  <main class="rail-example-content">
    <p class="rail-example-eyebrow">MATERIAL DESIGN · VARIANT 3</p>
    <h1 id="rail-view-title">Home</h1>
    <p id="rail-view-description" aria-live="polite">
      A place for the ideas, tools, and components that shape your next interface.
    </p>
    <!-- Decorative animation controlled by the pause button. -->
    <div class="rail-example-art" aria-hidden="true">
      <div></div>
      <i class="material-icons">auto_awesome</i>
    </div>
    <p class="rail-example-hint">
      Choose a section. Use the controls at the bottom of the rail to pause motion or
      switch the theme.
    </p>
  </main>
  <!-- Load the TypeScript below through your bundler. -->
  <script type="module" src="/sidenav-rail-demo.ts"></script>
</body>
SCSS — layout, colors, and responsive styles
@import 'material-icons/iconfont/material-icons.css';
@import 'kmaterialize/sass/materialize.scss';

.rail-example { margin: 0; background: var(--md-sys-color-background); color: var(--md-sys-color-on-background); }
.rail-example-content { margin-left: 104px; padding: 40px clamp(20px, 5vw, 64px); max-width: 1050px; }
.rail-example-content h1 { font-size: clamp(36px, 7vw, 80px); letter-spacing: -.05em; margin: 24px 0; }
.rail-example-content p { line-height: 1.6; max-width: 48ch; }
.rail-example-eyebrow { font-size: 10px; letter-spacing: .16em; color: var(--md-sys-color-on-surface-variant); }
.rail-example-hint { font-size: 13px; color: var(--md-sys-color-on-surface-variant); }
.rail-example-art {
  display: grid; place-items: center; position: relative; isolation: isolate;
  height: 240px; margin: 32px 0; overflow: hidden; border-radius: 36px;
  background: var(--md-sys-color-secondary-container); color: var(--md-sys-color-on-secondary-container);
  > div { position: absolute; width: 160px; height: 160px; background: var(--md-sys-color-tertiary-container); border-radius: 40%; animation: rail-orbit 18s linear infinite; z-index: -1; }
  > i { font-size: 64px; }
}
.rail-motion-paused .rail-example-art > div { animation-play-state: paused; }
@keyframes rail-orbit { to { transform: rotate(360deg); } }
@media (max-width: 480px) {
  .rail-example-content { margin-left: 88px; padding: 28px 20px; }
}
TypeScript — initialization and interactions
import {
  applyTheme,
  argbFromHex,
  themeFromSourceColor,
} from '@material/material-color-utilities';
import './sidenav-rail-demo.scss';

// Read the website theme, falling back to the device preference.
const systemTheme = matchMedia('(prefers-color-scheme: dark)');
const savedDark = () => {
  const preference = localStorage.getItem('theme-mode');
  return preference ? preference === 'dark' : systemTheme.matches;
};
// Cache controls and initialize their state. Reduced motion starts paused.
const themeButton = document.querySelector<HTMLButtonElement>('#rail-theme')!;
const motionButton = document.querySelector<HTMLButtonElement>('#rail-motion')!;
let dark = savedDark();
let paused = matchMedia('(prefers-reduced-motion: reduce)').matches;
// Generate colors from the saved website palette and update the theme button.
function updateTheme() {
  const seed = localStorage.getItem('theme-primary-color') || '#FFD700';
  const theme = themeFromSourceColor(argbFromHex(seed));
  applyTheme(theme, { target: document.documentElement, dark });
  document.documentElement.setAttribute('theme', dark ? 'dark' : 'light');
  themeButton.setAttribute('aria-label', `Switch to ${dark ? 'light' : 'dark'} theme`);
  themeButton.querySelector('i')!.textContent = dark ? 'light_mode' : 'dark_mode';
}
// Keep the animation, icon, and accessible button state in sync.
function updateMotion() {
  document.body.classList.toggle('rail-motion-paused', paused);
  motionButton.setAttribute('aria-pressed', String(paused));
  motionButton.setAttribute('aria-label', paused ? 'Resume motion' : 'Pause motion');
  motionButton.querySelector('i')!.textContent = paused ? 'play_arrow' : 'pause';
}
// Connect the two utility buttons.
themeButton.addEventListener('click', () => {
  dark = !dark;
  updateTheme();
});
motionButton.addEventListener('click', () => {
  paused = !paused;
  updateMotion();
});
// Changes made in the surrounding docs page also reach this iframe.
window.addEventListener('storage', (event) => {
  if (!event.key || ['theme-primary-color', 'theme-mode'].includes(event.key)) {
    dark = savedDark();
    updateTheme();
  }
});
systemTheme.addEventListener('change', () => {
  if (!localStorage.getItem('theme-mode')) {
    dark = savedDark();
    updateTheme();
  }
});
updateTheme();
updateMotion();
// Demo page content. Real applications would render their own routes here.
const descriptions: Record<string, string> = {
  Home: 'A place for the ideas, tools, and components that shape your next interface.',
  'Get started':
    'Start with the essentials and build a shared design language for your product.',
  Develop: 'Turn design decisions into working interfaces with reusable components.',
  Foundations:
    'Create a clear hierarchy with accessible layouts, interaction, and motion.',
  Styles: 'Make color, typography, and shape work together across your interface.',
  Components:
    'Explore the building blocks that help people navigate and get things done.',
  Blog: 'Discover new ideas and stories from the world of interface design.',
};
const links = Array.from(
  document.querySelectorAll<HTMLAnchorElement>('.m3-rail-nav a'),
);
// Update the active link and content when the URL hash changes.
function selectSection() {
  const selected = links.find((link) => link.hash === location.hash) || links[0];
  links.forEach((link) => {
    if (link === selected) link.setAttribute('aria-current', 'page');
    else link.removeAttribute('aria-current');
  });
  const name = selected.dataset.view!;
  document.querySelector('#rail-view-title')!.textContent = name;
  document.querySelector('#rail-view-description')!.textContent = descriptions[name];
}
window.addEventListener('hashchange', selectSection);
selectSection();

Initialization

document.addEventListener('DOMContentLoaded', function () {
  const elems = document.querySelectorAll('.sidenav');
  const instances = Sidenav.init(elems, {
    // specify options here
  });
});

// Initialize collapsible (uncomment the lines below if you use the dropdown variation)
// const collapsibleElem = document.querySelector('.collapsible');
// const collapsibleInstance = Collapsible.init(collapsibleElem, {
//  // specify options here
// });

Options

Name Type Default Description
edge String 'left' Side of screen on which Sidenav appears.
draggable Boolean true Allow swipe gestures to open/close Sidenav.
dragTargetWidth String '10px' Width of the area where you can start dragging.
inDuration Number 250 Length in ms of enter transition.
outDuration Number 200 Length in ms of exit transition.
onOpenStart Function null Function called when sidenav starts entering.
onOpenEnd Function null Function called when sidenav finishes entering.
onCloseStart Function null Function called when sidenav starts exiting.
onCloseEnd Function null Function called when sidenav finishes exiting.
preventScrolling Boolean true Prevent page from scrolling while sidenav is open.

Methods

All the methods are called on the plugin instance. You can get the plugin instance like this:

const instance = Sidenav.getInstance(elem);
.open();

Opens Sidenav.

instance.open();
.close();

Closes Sidenav.

instance.close();
.destroy();

Destroy plugin instance and teardown

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 Describes open/close state of Sidenav.
isFixed Boolean Describes if sidenav is fixed.
isDragged Boolean Describes if Sidenav is being dragged.

Close Trigger

Add the class .sidenav-close to an element inside the sidenav and any click event on that element will cause the sidenav to close. This is useful in Single Page Apps where the page does not refresh on link clicks.

<ul id="slide-out" class="sidenav">
  <li><a class="sidenav-close" href="#!">Clicking this will close Sidenav</a></li>
</ul>
<a href="#" data-target="slide-out" class="sidenav-trigger">
  <i class="material-icons">menu</i>
</a>

Variations

Here are some useful variations and additional elements you can add to your sidebar.

Dropdown HTML Structure

Add collapsible menus to your sidebar.

<ul id="slide-out" class="sidenav">
  <li><a href="#!">First Sidebar Link</a></li>
  <li><a href="#!">Second Sidebar Link</a></li>
  <li class="no-padding">
    <ul class="collapsible collapsible-accordion">
      <li>
        <a class="collapsible-header">
          Dropdown
          <i class="material-icons">arrow_drop_down</i>
        </a>
        <div class="collapsible-body">
          <ul>
            <li><a href="#!">First</a></li>
            <li><a href="#!">Second</a></li>
            <li><a href="#!">Third</a></li>
            <li><a href="#!">Fourth</a></li>
          </ul>
        </div>
      </li>
    </ul>
  </li>
</ul>
<ul class="right hide-on-med-and-down">
  <li><a href="#!">First Sidebar Link</a></li>
  <li><a href="#!">Second Sidebar Link</a></li>
  <li>
    <a class="dropdown-trigger" href="#!" data-target="dropdown1">
      Dropdown
      <i class="material-icons right">arrow_drop_down</i>
    </a>
  </li>
  <ul id="dropdown1" class="dropdown-content">
    <li><a href="#!">First</a></li>
    <li><a href="#!">Second</a></li>
    <li><a href="#!">Third</a></li>
    <li><a href="#!">Fourth</a></li>
  </ul>
</ul>
<a href="#" data-target="slide-out" class="sidenav-trigger">
  <i class="material-icons">menu</i>
</a>

Fullscreen HTML Structure

If you want the menu to be accessible on all screensizes you just have to add a simple helper class show-on-large to the .sidenav-trigger.

<ul id="slide-out" class="sidenav">
  <li><a href="#!">First Sidebar Link</a></li>
  <li><a href="#!">Second Sidebar Link</a></li>
</ul>
<a href="#" data-target="slide-out" class="sidenav-trigger show-on-large">
  <i class="material-icons">menu</i>
</a>

Fixed HTML Structure

Add the class sidenav-fixed to have the sidenav be fixed and open on large screens and hides to the regular functionality on smaller screens. Our sidenav on the left is an example of this.

<ul id="slide-out" class="sidenav sidenav-fixed">
  <li><a href="#!">First Sidebar Link</a></li>
  <li><a href="#!">Second Sidebar Link</a></li>
</ul>
<a href="#" data-target="slide-out" class="sidenav-trigger">
  <i class="material-icons">menu</i>
</a>

If you are planning on using this you will have to offset your content by the width of the side menu. Place the padding on where the offset content will be, which in our case is in header, main and footer.

header,
main,
footer {
  padding-left: 300px;
}

@media only screen and (max-width: 992px) {
  header,
  main,
  footer {
    padding-left: 0;
  }
}