html|css|javascript 54 views

Collapsible Sidebar Navigation Menu

Create a responsive and collapsible sidebar menu using HTML, CSS, and JavaScript. Perfect for maximizing screen space on smaller devices.

By TWC Team • Jan 28, 2026

Code

<!--
  Collapsible Sidebar Navigation Menu
  Responsive, accessible sidebar that toggles via button/ESC and supports reduced motion. Drop into any page.
-->
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Collapsible Sidebar Navigation Menu</title>
  <style>
    :root { --sidebar-w: 250px; --bg: #333; --fg: #fff; --focus: #7dd3fc; }
    body { margin: 0; font-family: Arial, sans-serif; min-height: 100vh; transition: margin-left .5s; }
    .sidebar {
      width: var(--sidebar-w);
      position: fixed;
      inset: 0 auto 0 calc(var(--sidebar-w) * -1); /* hidden by default */
      background: var(--bg);
      color: var(--fg);
      padding: 15px;
      transition: left .5s;
      z-index: 1000;
      box-sizing: border-box;
    }
    .sidebar.active { left: 0; }
    #toggleBtn {
      appearance: none;
      border: 1px solid rgba(255,255,255,.25);
      background: transparent;
      color: var(--fg);
      padding: 10px 12px;
      border-radius: 8px;
      cursor: pointer;
    }
    #toggleBtn:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
    .menu { padding: 12px 0 0; margin: 0; }
    .menu li { list-style: none; margin: 12px 0; }
    .menu a { color: var(--fg); text-decoration: none; display: inline-block; padding: 6px 4px; border-radius: 6px; }
    .menu a:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

    /* Small screens: push content when open; larger screens keep overlay behavior */
    @media (max-width: 720px) { body.sidebar-open { margin-left: var(--sidebar-w); } }
    @media (prefers-reduced-motion: reduce) { body, .sidebar { transition: none; } }
  </style>
</head>
<body>
  <div class="sidebar" id="sidebar" aria-hidden="true">
    <button id="toggleBtn" type="button" aria-controls="sidebar" aria-expanded="false">Toggle Menu</button>
    <ul class="menu">
      <li><a href="#">Home</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Services</a></li>
      <li><a href="#">Contact</a></li>
    </ul>
  </div>

  <main style="padding: 20px;">
    <h1>Page Content</h1>
    <p>Example usage: click “Toggle Menu”, press Escape to close.</p>
  </main>

  <script>
    // Sidebar toggle with accessibility (aria-*), ESC close, and safe init.
    (() => {
      const sidebar = document.getElementById('sidebar');
      const toggleBtn = document.getElementById('toggleBtn');
      if (!sidebar || !toggleBtn) return;

      const setOpen = (isOpen) => {
        sidebar.classList.toggle('active', isOpen);
        document.body.classList.toggle('sidebar-open', isOpen);
        sidebar.setAttribute('aria-hidden', String(!isOpen));
        toggleBtn.setAttribute('aria-expanded', String(isOpen));
      };

      toggleBtn.addEventListener('click', () => setOpen(!sidebar.classList.contains('active')));
      document.addEventListener('keydown', (e) => { if (e.key === 'Escape') setOpen(false); }, { passive: true });

      // Example usage: call setOpen(true/false) to control programmatically.
    })();
  </script>
</body>
</html>
Back to Snippets