aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Frontend & UI

Hamburgermenu maken: toegankelijke mobiele navigatie

Op mobiele apparaten is het scherm smal, waardoor een horizontale menubalk er zelden op past. Precies daar bewijst het hamburgermenu zijn waarde: een kleine knop van drie streepjes die bij een tik de navigatielinks tevoorschijn brengt. In dit artikel bouwen we stap voor stap een toegankelijke, vloeiende mobiele navigatie met pure HTML, CSS en JavaScript, zonder enige bibliotheek.

Het geraamte: betekenisvolle HTML

Een goed menu begint met semantische opmaak die ook zonder JavaScript logisch blijft. Schrijf de trigger als een echte <button>, geen <div>. Voeg aria-expanded en aria-controls toe zodat schermlezers de toestand begrijpen.

<header class="site-header">
  <a href="/" class="logo">aslain</a>

  <button id="navToggle" class="nav-toggle"
          aria-expanded="false"
          aria-controls="primaryNav"
          aria-label="Menu openen">
    <span class="bar"></span>
    <span class="bar"></span>
    <span class="bar"></span>
  </button>

  <nav id="primaryNav" class="nav">
    <ul>
      <li><a href="/#about">Over mij</a></li>
      <li><a href="/#projects">Projecten</a></li>
      <li><a href="/#contact">Contact</a></li>
    </ul>
  </nav>
</header>

De drie <span class="bar"> zijn de streepjes van het pictogram. Ze in CSS tekenen is lichter dan een afbeeldingsbestand gebruiken en laat je kleur en animatie eenvoudig sturen.

Het pictogram met CSS tekenen

We gebruiken een media query om de knop alleen op smalle schermen te tonen. Op brede schermen is het menu al horizontaal en blijft de hamburgerknop verborgen.

.nav-toggle {
  display: none;            /* verborgen op desktop */
  width: 44px;
  height: 44px;            /* minstens 44px aanraakzone */
  background: none;
  border: 0;
  cursor: pointer;
}
.nav-toggle .bar {
  display: block;
  width: 24px;
  height: 2px;
  margin: 5px auto;
  background: currentColor;
  transition: transform .25s ease, opacity .25s ease;
}

@media (max-width: 760px) {
  .nav-toggle { display: block; }
}

Mik op een aanraakzone van minstens 44×44 pixels; dat is een veilige maat die een vinger comfortabel raakt en die toegankelijkheidsrichtlijnen aanbevelen.

De open- en sluitlaag

Op smalle schermen verbergen we het menupaneel standaard en tonen het wanneer een klasse .is-open wordt toegevoegd. transform en visibility gebruiken in plaats van display: none houdt de schuifovergang vloeiend.

@media (max-width: 760px) {
  .nav {
    position: fixed;
    inset: 64px 0 0 0;          /* begint onder de header */
    background: #0f0f12;
    transform: translateX(100%);
    visibility: hidden;
    transition: transform .3s ease, visibility .3s;
  }
  .nav.is-open {
    transform: translateX(0);
    visibility: visible;
  }
  .nav ul {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    padding: 2rem;
  }
}

De drie streepjes in een "X" veranderen maakt duidelijk dat het menu open is. We doen dit alleen met CSS: de bovenste en onderste balk draaien, de middelste verdwijnt.

.nav-toggle.is-active .bar:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.nav-toggle.is-active .bar:nth-child(2) {
  opacity: 0;
}
.nav-toggle.is-active .bar:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

JavaScript: toestand en toegankelijkheid

De enige taak van JavaScript is klassen wisselen en aria-expanded bijwerken. De toestand in aria-expanded als enige bron van waarheid houden, houdt de code schoon.

const toggle = document.getElementById('navToggle');
const nav = document.getElementById('primaryNav');

function setOpen(open) {
  toggle.setAttribute('aria-expanded', String(open));
  toggle.classList.toggle('is-active', open);
  nav.classList.toggle('is-open', open);
  toggle.setAttribute('aria-label', open ? 'Menu sluiten' : 'Menu openen');
}

toggle.addEventListener('click', () => {
  const open = toggle.getAttribute('aria-expanded') === 'true';
  setOpen(!open);
});

// Sluit het menu wanneer op een link wordt getikt
nav.addEventListener('click', (e) => {
  if (e.target.closest('a')) setOpen(false);
});

// De Escape-toets sluit het menu
document.addEventListener('keydown', (e) => {
  if (e.key === 'Escape') setOpen(false);
});

Drie kleine maar belangrijke details om op te merken:

  • Sluiten bij linkklik: op een one-page-site is het vervelend als het menu open blijft nadat de gebruiker naar een sectie is gesprongen.
  • Escape-ondersteuning: toetsenbordgebruikers verwachten dat de Esc-toets het menu sluit.
  • aria-label bijwerken: het label wisselen tussen "openen" en "sluiten" geeft de schermlezer de juiste informatie.

Focusbeheer en bodyscroll

Voorkomen dat de pagina achter het menu scrollt zolang het open is, is een belangrijk detail op mobiel. Je kunt een klasse aan <body> toevoegen en overflow: hidden toepassen. De focus naar de eerste link verplaatsen bij het openen maakt de flow ook natuurlijk voor toetsenbord- en schermlezergebruikers.

function setOpen(open) {
  /* ...vorige regels... */
  document.body.classList.toggle('nav-locked', open);
  if (open) nav.querySelector('a')?.focus();
  else toggle.focus();
}
body.nav-locked { overflow: hidden; }

De focus weer naar de hamburgerknop sturen bij het sluiten laat de gebruiker verdergaan waar die was gebleven. Dit kleine focusherstel is het kenmerk van een toegankelijk component.

Respect voor de voorkeur voor minder beweging

Sommige gebruikers kiezen ervoor om beweging te verminderen in hun systeeminstellingen. Animaties uitschakelen om die voorkeur te eren is zowel beleefd als toegankelijk.

@media (prefers-reduced-motion: reduce) {
  .nav, .nav-toggle .bar { transition: none; }
}

Deze paar regels laten bewegingsgevoelige gebruikers het menu bedienen zonder abrupte overgangen, zonder verlies van functionaliteit.

Veelgestelde vragen

Waarom een <button> in plaats van een <div>?

Een echte <button> is focusbaar met het toetsenbord, werkt met de Enter- en Spatie-toetsen en wordt als "knop" aangekondigd aan schermlezers. Met een <div> moet je dat allemaal met de hand nabootsen, wat extra code en een bron van bugs betekent.

Is een afbeelding of CSS beter voor het hamburgerpictogram?

In de meeste gevallen is drie <span>-elementen tekenen met CSS beter: geen extra verzoek, de kleur volgt het thema via currentColor, en je kunt de transformatie naar een X rechtstreeks animeren. SVG is ook een geldige keuze.

Bij welke breedte moet het menu inklappen?

Er is geen vaste regel; kijk naar je inhoud. Het breekpunt plaatsen waar het horizontale menu niet meer past (vaak rond 700–800px) werkt goed. Test je ontwerp door de browser te versmallen.

Wil je dat je mobiele menu zowel elegant als toegankelijk is? Laten we samen de navigatie van je site bekijken. Neem contact op en laten we over je project praten.

Bu kategorideki tüm yazılar →

Devamı için