Skip to content

Bun and Done

Time to put a bun on this thing.
You’ve tamed the rigid menu with Flexbox — now the nav learns its first party trick: the classic hamburger button that shows and hides a dropdown.

This chapter keeps it simple:

  • one hamburger button
  • one dropdown panel
  • a tiny JavaScript toggle
  • no animations (yet)

Think: solid baseline before the fancy stuff.


Flexbox helped the menu adapt, but on small screens:

  • even “nicely wrapped” nav can hog vertical space
  • dense menus become scroll-heavy
  • users expect a compact menu icon they can summon on demand

The hamburger lets you:

  • hide the menu off-screen by default
  • show it on tap
  • leave plenty of room for content

We start from the shared structure and add a toggle button and an id for the nav:

<header class="site-header">
<div class="brand-lockup">
<span class="site-logo"></span>
<span class="site-title">WebDevTnT</span>
</div>
<button
class="nav-toggle"
type="button"
aria-expanded="false"
aria-controls="site-nav"
>
<span class="visually-hidden">Toggle navigation</span>
<span class="nav-toggle-line"></span>
<span class="nav-toggle-line"></span>
<span class="nav-toggle-line"></span>
</button>
<nav id="site-nav" class="site-nav" aria-label="Main">
<ul class="nav-list">
<li><a href="#">Overview</a></li>
<li><a href="#">Lessons</a></li>
<li><a href="#">Demos</a></li>
<li><a href="#">Assignments</a></li>
<li><a href="#">Resources</a></li>
</ul>
</nav>
</header>

The button is always in the DOM; CSS will decide when to show or hide it.


On narrow screens the nav is hidden by default and appears below the header when open.

/* Base header layout */
.site-header {
width: 100%;
max-width: 960px;
margin: 2rem auto;
padding: 1rem 1.5rem;
background: #020617;
color: #e5e7eb;
border-radius: 999px;
display: flex;
align-items: center;
justify-content: space-between;
}
/* Hamburger button */
.nav-toggle {
display: inline-flex;
flex-direction: column;
justify-content: center;
gap: 4px;
width: 40px;
height: 40px;
border-radius: 999px;
border: 1px solid rgba(148, 163, 184, 0.8);
background: rgba(15, 23, 42, 0.95);
}
.nav-toggle-line {
width: 18px;
height: 2px;
border-radius: 999px;
background: #e5e7eb;
}
/* Nav panel — hidden by default on mobile */
.site-nav {
position: static;
width: 100%;
max-width: 960px;
margin: 0.75rem auto 0;
padding: 0.75rem 1.5rem;
border-radius: 1rem;
background: #020617;
border: 1px solid rgba(148, 163, 184, 0.6);
display: none; /* 👈 default: hidden on small screens */
}
.site-nav.is-open {
display: block; /* 👈 shown when toggled */
}
.nav-list {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
/* Desktop: show inline menu, hide hamburger, no dropdown */
@media (min-width: 960px) {
.site-header {
border-radius: 999px;
margin-bottom: 0;
}
.nav-toggle {
display: none;
}
.site-nav {
display: block;
position: static;
margin: 0;
padding: 0;
border: none;
background: transparent;
}
.nav-list {
flex-direction: row;
gap: 1rem;
justify-content: flex-end;
}
}

Mobile: compact header + toggle + hidden menu.
Desktop: classic inline nav bar, like before.


Just enough JS to flip the is-open class and keep aria-expanded honest.

const navToggle = document.querySelector('.nav-toggle');
const nav = document.querySelector('#site-nav');
if (navToggle && nav) {
navToggle.addEventListener('click', () => {
const isOpen = nav.classList.toggle('is-open');
navToggle.setAttribute('aria-expanded', String(isOpen));
});
}

That’s it. No libraries, no framework code, just standard DOM + events.


This one plays nicely — resize away, and tap the bun to drop or hide the menu.

WebDevTnT

Tap the bun, drop the nav.


Pack these in your mental to-go box:

  • The hamburger button doesn’t do anything until JS wires it up.
  • aria-expanded communicates state to assistive tech — keep it honest.
  • Mobile-first CSS: hide dropdown by default, reveal it with a class (.is-open).
  • Desktop can completely ignore the hamburger and just render a normal nav.
  • This pattern is your baseline for every fancier menu that follows.

04 · Sneaky Slideout
Same button, same toggle logic — but the menu stops dropping down and starts sliding in from the side.