Dynamic Sidebar Starter (Swipe-to-Close)
A small, framework-free starter for a responsive off‑canvas sidebar with a shared navigation file (nav.html), plus a clean baseline UI.
Clone it, change the menu + colours, and you’ve got a solid starting point for a simple multi‑page site, dashboard, or prototype.
Highlights
- Shared navigation: edit
nav.html once, updates across pages
- Off‑canvas sidebar: slide-in drawer + backdrop overlay
- Mobile-friendly: swipe left on the sidebar to close (default threshold included)
- Keyboard-friendly: Escape closes the sidebar; button state stays in sync
- Progressive enhancement:
<noscript> fallback nav is present on each page
- Accessible foundation: skip link, ARIA attributes, focus styles
Quick start
1) Clone
git clone https://github.com/sargentJE/dynamic_sidebar_with_swipe.git
cd dynamic_sidebar_with_swipe
2) Run locally (recommended)
Because the sidebar loads nav.html via fetch(), you should serve the folder over HTTP. (Opening pages using file:// may block requests in some browsers.)
Python
python3 -m http.server 8000
Open:
Node
npx serve .
Project layout
.
├─ index.html
├─ about.html
├─ contact.html
├─ nav.html
├─ css/
│ ├─ styles.css
│ └─ contactForm.css (used by the contact example)
└─ js/
└─ sidebar.js
Controls (what users can do)
- Click ☰ Menu to open/close
- Click the backdrop to close
- Press Escape to close
- Swipe left on the sidebar to close (touch devices)
How it works
Shared navigation (nav.html)
Your navigation lives in one file: nav.html.
On first open, the script loads it and injects it into the sidebar container:
- It loads once, then reuses the HTML on subsequent opens.
- It also preloads the nav on button hover/focus to reduce perceived delay.
Sidebar behaviour (js/sidebar.js)
At a high level:
- When the menu button is activated, the script ensures
nav.html is loaded.
- It toggles an “open” class on the sidebar and shows/hides the backdrop.
- It keeps
aria-expanded updated on the button and sets aria-hidden on the main content while the sidebar is open.
- It listens for Escape and for a leftward swipe on the sidebar.
Sidebar styling (css/styles.css)
The sidebar is off-canvas by default using a translate transform, and becomes visible when open.
You can tweak:
- width via
--sidebar-w
- colours via CSS variables
- the slide animation via
transition
Customise in 5 minutes (recommended checklist)
-
Change the site name
- Update the
<title> and any header text in your pages.
-
Update the menu
- Edit
nav.html and adjust the links.
-
Update the home page links
index.html contains placeholder links — search for:
- Replace with your domain/host.
-
Set your theme
- In
css/styles.css, tweak variables like:
--brand, --surface, --panel, --ink, --focus
-
Remove example pages (optional)
- Delete
about.html / contact.html if you don’t need them.
Adding a new page
Copy an existing page (e.g. about.html) and keep these pieces:
- The stylesheet:
<link rel="stylesheet" href="css/styles.css" />
- The nav prefetch (optional but helpful):
<link rel="prefetch" href="nav.html" as="fetch" />
- The toggle button:
<button id="sidebarToggle" class="toggle-btn"
aria-controls="sidebar" aria-expanded="false">
☰ Menu
</button>
- The backdrop + sidebar container (with
<noscript> fallback):
<div id="backdrop" class="backdrop" hidden></div>
<aside id="sidebar" class="sidebar" aria-labelledby="menu-heading">
<noscript>
<!-- Fallback nav for when JS is disabled -->
<!-- (copy the same nav structure here) -->
</noscript>
</aside>
- The script:
<script type="module" src="js/sidebar.js" defer></script>
Accessibility notes
Included out of the box:
- Skip link (“Skip to content”)
- Clear focus styles
aria-controls / aria-expanded on the toggle button
aria-hidden on main content when the sidebar is open
<noscript> fallback navigation
Good upgrades if you extend this template:
- Focus management (move focus into the sidebar on open; restore focus on close)
- Focus trap while open (treat the sidebar like a “drawer”/modal)
- Scroll lock to prevent background scroll on mobile
- Reduced motion support via
prefers-reduced-motion (if you add more animation)
Troubleshooting
The sidebar opens but navigation is empty
You’re probably running the pages via file://.
Fix: run a local server (see Quick start) so fetch('nav.html') works.
Deploying
This is a static site, so it works well on:
- GitHub Pages
- Netlify / Vercel
- any static web host
If you move files around, make sure the fetch('nav.html') path in js/sidebar.js still points to the correct location.
License
No license is included yet. If you want others to freely reuse this starter, add a LICENSE file (MIT is a common choice for starter templates).