CSS Tabs Generator

Volgende

Tabs zijn overal, instellingenpanelen, documentatiesites, productgalerijen. HTML heeft geen ingebouwd tab-element, dus developers bouwen hun eigen variant. Deze generator bouwt een eenvoudige tabbalk in HTML + CSS: een accentkleur voor de actieve tab, een hoekradius voor de knoppen en een hover-status. Plak de markup in je project en koppel het wisselen van tabs aan je eigen JavaScript.

Zo bouw je tabs

  1. 1

    Kies een accentkleur

    De achtergrond- en tekstkleur van de actieve tab. Kies een kleur die past bij je merk.

  2. 2

    Stel de hoekradius in

    Rondt de bovenste hoeken van de tabknoppen af. Hogere waarden geven een zachtere uitstraling.

  3. 3

    Bewerk de labels

    De uitvoer bevat drie knoppen, "Overview", "Details" en "Settings": hernoem ze zodat ze bij je inhoud passen.

  4. 4

    Kopieer de code

    De tab-markup wordt geleverd met een eigen <style>-blok. Plak beide in je pagina.

  5. 5

    Voeg tabwisseling toe

    De generator maakt alleen het visuele deel. Koppel de knoppen aan je eigen JavaScript of UI-bibliotheek om de panelen te tonen en te verbergen.

Correcte toegankelijke markup

<div class="tabs">
  <div role="tablist" aria-label="Product info">
    <button role="tab" id="tab-1" aria-selected="true"  aria-controls="panel-1" tabindex="0">Overzicht</button>
    <button role="tab" id="tab-2" aria-selected="false" aria-controls="panel-2" tabindex="-1">Specs</button>
    <button role="tab" id="tab-3" aria-selected="false" aria-controls="panel-3" tabindex="-1">Reviews</button>
  </div>
  <section role="tabpanel" id="panel-1" aria-labelledby="tab-1">...</section>
  <section role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>...</section>
  <section role="tabpanel" id="panel-3" aria-labelledby="tab-3" hidden>...</section>
</div>

Cruciale attributen:

  • role="tablist" wikkelt om de knoppen.
  • role="tab" op elke knop, met aria-selected en aria-controls.
  • tabindex gebruikt het roving tabindex-patroon: alleen de actieve tab is 0, de rest is -1. Pijltoetsen verplaatsen focus daartussen.
  • role="tabpanel" op elk panel, met aria-labelledby dat naar zijn tab wijst.
  • hidden op inactieve panels (niet alleen display: none, het attribuut is wat AT gebruikt).

Toetsenbord-contract

Toets Actie
Tab Naar de tablist in / eruit
ArrowLeft Vorige tab (loopt door naar de laatste)
ArrowRight Volgende tab (loopt door naar de eerste)
Home Eerste tab
End Laatste tab
Enter / Space Activeer de gefocuste tab (bij handmatige activatie)

Automatische activatie (tab wisselt zodra focus verschuift) versus manueel (focus beweegt, tab activeert bij Enter), WAI-ARIA staat beide toe. Automatisch is makkelijker voor ziende gebruikers; manueel is beter wanneer tab-content zwaar te renderen is.

Onderstreepte stijl

[role="tablist"] {
  display: flex;
  border-bottom: 1px solid #e5e7eb;
}
[role="tab"] {
  padding: 0.75rem 1rem;
  background: transparent;
  border: 0;
  color: #6b7280;
  position: relative;
  cursor: pointer;
}
[role="tab"][aria-selected="true"] {
  color: #111827;
}
[role="tab"][aria-selected="true"]::after {
  content: "";
  position: absolute;
  left: 1rem; right: 1rem; bottom: -1px;
  height: 2px;
  background: #2563eb;
}

Pil-stijl

[role="tab"] {
  padding: 0.5rem 0.9rem;
  border-radius: 9999px;
  border: 0;
  background: transparent;
}
[role="tab"][aria-selected="true"] {
  background: #2563eb;
  color: #fff;
}

Focus zichtbaar maken

Teken altijd een focusring wanneer de focus via het toetsenbord aankomt:

[role="tab"]:focus-visible {
  outline: 2px solid #60a5fa;
  outline-offset: 2px;
}

Het JavaScript

Grofweg:

const tabs = document.querySelectorAll('[role="tab"]');
tabs.forEach(tab => {
  tab.addEventListener('click', () => activate(tab));
  tab.addEventListener('keydown', e => {
    const i = [...tabs].indexOf(tab);
    if (e.key === 'ArrowRight') tabs[(i + 1) % tabs.length].focus();
    if (e.key === 'ArrowLeft')  tabs[(i - 1 + tabs.length) % tabs.length].focus();
    if (e.key === 'Home') tabs[0].focus();
    if (e.key === 'End')  tabs[tabs.length - 1].focus();
  });
});

function activate(tab) {
  tabs.forEach(t => {
    const panel = document.getElementById(t.getAttribute('aria-controls'));
    const active = t === tab;
    t.setAttribute('aria-selected', active);
    t.setAttribute('tabindex', active ? '0' : '-1');
    panel.hidden = !active;
  });
  tab.focus();
}

Dertig regels in totaal, nul afhankelijkheden.

Tabs vs. accordeons

Op smalle schermen worden tab-rijen krap. Veelvoorkomend patroon: tabs op desktop, accordeon op mobiel. Gebruik een container query of media query om de visuele weergave te wisselen zonder de ARIA-rollen te veranderen.

Veelgestelde vragen

Voor toegankelijke tabs wel. Zonder role="tablist" en role="tab" behandelen screenreaders de knoppen als gewone buttons en verliezen gebruikers de navigatieconventie. Het alternatief is een platte <details> / <summary>-accordion, die ingebouwde semantiek heeft.

Automatisch (tab activeert zodra focus verschuift) is prima wanneer de content van elke tab goedkoop te renderen is. Manueel (focus beweegt, Enter activeert) is beter wanneer wisselen van tab zwaar werk triggert zoals fetchen of het renderen van een groot formulier.

Voor content-dragende tabs (documentatie, producttabs), ja, gebruik een hash (#specs) of query param zodat links deep kunnen linken naar een specifieke tab en de actieve tab over reloads heen blijft. Voor UI-tabs (settings-panelen) is de URL optioneel.

Alleen met de checkbox/radio-hack, die geen pijltoetsnavigatie en ARIA-staten heeft. Voor een echt toegankelijke implementatie is het kleine JS-snippet de moeite waard. Heb je server-rendered fallbacks nodig, link elke tab dan aan een eigen URL en render het bijbehorende panel server-side.

Gerelateerde tools

Tool beschikbaar in andere talen