Flexbox verscheen in alle grote browsers rond 2015 en loste meteen het probleem op waar ontwikkelaars al een decennium omheen werkten: verticaal centreren. Maar de meeste mensen leerden het achterstevoren — ze memoriseerden justify-content: center van een cheatsheet zonder te begrijpen waarom het werkt. Wanneer de layout zich niet gedraagt, verandert die lacune in begrip een taak van vijf minuten in een uur van trial and error. Deze gids bouwt eerst het mentale model op en behandelt daarna elke eigenschap die echt van belang is in echte projecten.

Het Mentale Model: Één As Tegelijk

Het kernconceptvan Flexbox is dat het items langs één as uitlijnt. Er is een hoofdas — de richting waarin items stromen — en een dwarsas, die loodrecht loopt. Het cruciale inzicht dat bijna elke beginner mist: flex-direction bepaalt welke as welke is. Al het andere volgt daaruit.

css
/* Default: main axis runs LEFT → RIGHT, cross axis runs TOP → BOTTOM */
.container {
  display: flex;
  flex-direction: row; /* default */
}

/* Rotated: main axis now runs TOP → BOTTOM, cross axis runs LEFT → RIGHT */
.container {
  display: flex;
  flex-direction: column;
}

/*
  justify-content  →  controls alignment on the MAIN axis
  align-items      →  controls alignment on the CROSS axis

  This is why centering something in both axes looks like this:
*/
.center-both {
  display: flex;
  justify-content: center; /* horizontally centred (main axis = row) */
  align-items: center;     /* vertically centred (cross axis)        */
}
De verwarring die iedereen struikelt: wanneer je overschakelt naar flex-direction: column, beheert justify-content niet langer horizontale uitlijning — het beheert verticale uitlijning, omdat de hoofdas is gedraaid. align-items beheert nu de horizontale uitlijning. Houd deze rotatie in gedachten wanneer iets niet uitlijnt waar je het verwacht.

Containereigenschappen

Deze eigenschappen worden op de flex-container gezet — het bovenliggende element met display: flex. Ze bepalen hoe alle onderliggende items worden verdeeld en uitgelijnd.

css
/* display: flex makes the element a block-level flex container.
   display: inline-flex makes it inline (sits in text flow). */
.nav {
  display: flex;
}

/* flex-direction — which way does the main axis run? */
.nav {
  flex-direction: row;         /* left to right (default)  */
  flex-direction: row-reverse; /* right to left            */
  flex-direction: column;      /* top to bottom            */
  flex-direction: column-reverse; /* bottom to top         */
}

/* flex-wrap — what happens when items overflow the container? */
.card-grid {
  flex-wrap: nowrap;       /* all items forced onto one line (default) */
  flex-wrap: wrap;         /* items wrap onto additional lines         */
  flex-wrap: wrap-reverse; /* items wrap in reverse order              */
}

/* gap — space between items. Modern approach; avoids margin hacks. */
.card-grid {
  gap: 1.5rem;             /* same in both directions              */
  gap: 1rem 2rem;          /* row-gap column-gap                   */
}

De gap-eigenschap verdient een speciale vermelding. Voordat die bestond, was het gebruikelijke patroon marges aan flex-items toevoegen en dan de buitenste randen annuleren met negatieve marges. gap vervangt dat alles op een nette manier — gebruik het overal in plaats daarvan.

css
/* justify-content — alignment on the MAIN axis */
.nav {
  justify-content: flex-start;    /* packed to start (default)              */
  justify-content: flex-end;      /* packed to end                          */
  justify-content: center;        /* packed to centre                       */
  justify-content: space-between; /* first/last at edges, equal gaps between */
  justify-content: space-around;  /* equal space around each item           */
  justify-content: space-evenly;  /* equal space between every gap          */
}

/* align-items — alignment on the CROSS axis (single line) */
.nav {
  align-items: stretch;   /* items fill cross-axis height (default)         */
  align-items: flex-start;/* items align to start of cross axis             */
  align-items: flex-end;  /* items align to end of cross axis               */
  align-items: center;    /* items centred on cross axis                    */
  align-items: baseline;  /* items aligned by their text baseline           */
}

/* align-content — cross-axis alignment when there are MULTIPLE lines
   (only takes effect with flex-wrap: wrap and enough items to wrap) */
.card-grid {
  flex-wrap: wrap;
  align-content: flex-start;    /* rows packed to top                       */
  align-content: center;        /* rows centred vertically                  */
  align-content: space-between; /* rows spread out with space between       */
}

Hier is een echte navigatiebalk die dit combineert. Het logo staat links en de navigatielinks worden naar rechts geduwd met margin-left: auto — een klassieke Flexbox-truc. De aanpak met justify-content: space-between werkt ook, maar de auto-margin techniek is flexibeler wanneer je meer dan twee groepen hebt.

css
/* Nav: logo left, links right */
.site-nav {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0 2rem;
  height: 64px;
  background: #1a1a2e;
}

.site-nav .logo {
  font-size: 1.25rem;
  font-weight: 700;
  color: #fff;
  text-decoration: none;
}

.site-nav .nav-links {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  margin-left: auto; /* pushes everything after it to the right */
  list-style: none;
  margin-top: 0;
  margin-bottom: 0;
  padding: 0;
}

.site-nav .nav-links a {
  color: #ccc;
  text-decoration: none;
  font-size: 0.9rem;
}

.site-nav .nav-links a:hover {
  color: #fff;
}

Item-eigenschappen

Deze eigenschappen worden op de flex-items gezet — de directe kinderen van de flex-container. Ze bepalen hoe individuele items groeien, krimpen en zichzelf dimensioneren.

  • flex-grow — hoeveel van de beschikbare vrije ruimte dit item opeist. Standaard 0 (niet groeien). Stel in op 1 op een item en het neemt alle resterende ruimte.
  • flex-shrink — hoeveel dit item krimpt ten opzichte van anderen wanneer er onvoldoende ruimte is. Standaard 1. Stel in op 0 om te voorkomen dat een item krimpt.
  • flex-basis — de initiële grootte van het item vóór groei of krimp. Kan een lengte zijn (250px, 30%) of auto (gebruik de inhoudsgrootte van het item).
  • align-self — overschrijft align-items voor één specifiek item. Accepteert dezelfde waarden: auto, flex-start, flex-end, center, baseline, stretch.
  • order — verandert de visuele volgorde zonder de HTML aan te raken. Standaard 0. Lagere waarden verschijnen eerst. Gebruik spaarzaam — het doorbreekt de tabvolgorde en veroorzaakt toegankelijkheidsproblemen voor toetsenbord- en schermlezergebruikers.
css
/* Classic sidebar + main content layout */
.app-layout {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  flex: 0 0 280px; /* don't grow, don't shrink, always 280px wide */
  background: #f5f5f5;
  padding: 2rem 1.5rem;
}

.main-content {
  flex: 1; /* grow to fill all remaining space */
  padding: 2rem;
  min-width: 0; /* critical: prevents content overflow in flex children */
}

/* Responsive: stack vertically on mobile */
@media (max-width: 768px) {
  .app-layout {
    flex-direction: column;
  }

  .sidebar {
    flex: none; /* reset — don't use flex-basis on column layout */
  }
}
Het min-width: 0-probleem: Standaard kunnen flex-items niet krimpen tot onder hun minimale inhoudsgrootte. Als je een lang woord of een brede tabel in een flex-item hebt, zal het overlopen in plaats van omslaan. min-width: 0 toevoegen aan het flex-item lost dit op. Het komt constant voor bij het hoofdinhoudsgebied in zijbalklay-outs.

De flex Afkorting Uitgelegd

De flex-afkorting combineert flex-grow, flex-shrink en flex-basis in één declaratie. De W3C-specificatie definieert een handvol sleutelwoordwaarden die de gebruikelijke gevallen dekken, en ze worden vaak met elkaar verward.

css
/* flex: 1
   Expands to: flex-grow: 1; flex-shrink: 1; flex-basis: 0%
   Meaning: grow and shrink freely; start from zero (ignore content size).
   All items with flex: 1 share space equally, regardless of content.
   Most common choice for "fill available space". */
.tab { flex: 1; }

/* flex: auto
   Expands to: flex-grow: 1; flex-shrink: 1; flex-basis: auto
   Meaning: grow and shrink freely; start from the item's content size.
   Items with more content get more space — proportional, not equal. */
.column { flex: auto; }

/* flex: none
   Expands to: flex-grow: 0; flex-shrink: 0; flex-basis: auto
   Meaning: completely rigid — don't grow, don't shrink, stay at content size.
   Use for items that should never flex (icons, avatars, fixed labels). */
.avatar { flex: none; }

/* flex: 0 0 200px
   Explicit: don't grow, don't shrink, always exactly 200px.
   Same as writing out all three values. More readable for fixed-size items. */
.sidebar { flex: 0 0 200px; }

/* Practical difference: flex: 1 vs flex: auto in a tab bar
   With flex: 1  → all tabs are equal width regardless of label length
   With flex: auto → "Settings" tab is wider than "Home" tab */
.tabs { display: flex; }
.tab-equal  { flex: 1;    } /* equal width tabs     */
.tab-auto   { flex: auto; } /* content-sized tabs   */

Veelgebruikte Echte Lay-outs

Hier zijn vier patronen die je regelmatig zult gebruiken — gebouwd met niets anders dan Flexbox.

css
/* 1. Sticky footer
   The footer always sits at the bottom, even on short pages.
   body (or .app-shell) becomes a column flex container. */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  margin: 0;
}

main {
  flex: 1; /* expands to push footer down */
}

footer {
  /* stays at the bottom */
}
css
/* 2. Centred modal / hero content
   Both axes centred — the Flexbox vertical-centring party trick. */
.hero {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  padding: 2rem;
  background: linear-gradient(135deg, #667eea, #764ba2);
}

.hero-content {
  max-width: 640px;
  text-align: center;
  color: #fff;
}
css
/* 3. Nav bar: logo left, links right */
.site-nav {
  display: flex;
  align-items: center;
  padding: 0 2rem;
  height: 64px;
}

.site-nav .nav-links {
  margin-left: auto; /* auto margin consumes all free space to its left */
  display: flex;
  gap: 1.5rem;
  list-style: none;
  padding: 0;
  margin-top: 0;
  margin-bottom: 0;
}
css
/* 4. Card row that wraps on mobile */
.card-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
}

.card {
  flex: 1 1 280px; /* grow and shrink, but never below 280px wide */
  background: #fff;
  border-radius: 8px;
  padding: 1.5rem;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

/* On wide screens: 3-4 cards per row.
   On narrow screens: cards wrap into their own rows automatically.
   No media query needed for the wrap itself — flex-wrap handles it. */

Flexbox vs Grid — Wanneer Welke Gebruiken

Deze vraag komt constant naar voren, en het antwoord is eenvoudiger dan de meeste artikelen doen voorkomen: Flexbox is voor eendimensionale lay-outs. CSS Grid is voor tweedimensionale lay-outs. Als je items in één rij of één kolom uitlijnt — een navigatiebalk, een knoppengroep, een kaartrij — is Flexbox het juiste gereedschap. Als je rijen en kolommen tegelijkertijd moet beheren — een volledige paginalay-out, een fotomozaïek, een formulierraster — gebruik dan Grid.

In de praktijk gebruik je beide in hetzelfde project. Grid verwerkt de paginaniveaustructuur (koptekst, zijbalk, hoofd, voettekst). Flexbox verwerkt de componenten binnen die regio's (de navigatiebalk, de kaartinhoud, de knoppen in een modal). Ze vullen elkaar aan in plaats van te concurreren.

Het ene grijze gebied: kaartrasters die rijen van gelijke hoogte moeten hebben met items die in kolommen zijn uitgelijnd. Flexbox met flex-wrap: wrap kan dit, maar items in dezelfde visuele rij hebben geen relatie met elkaar — hun hoogtes zijn onafhankelijk. De impliciete rijgrootte van Grid verwerkt dit automatisch. Als je de kaarten in een omgeslagen rij allemaal dezelfde hoogte nodig hebt EN hun interne elementen over kaarten moeten uitlijnen, is Grid schoner.

Samenvatting

Het Flexbox mentale model is: kies een richting, begrijp welke eigenschappen welke as besturen, en kies dan of items moeten groeien, krimpen of vast moeten blijven. Zodra dat klikt, wordt het cheatsheet een opzoekwerk — geen kruk meer. De MDN Flexbox-gids is de beste referentie voor randgevallen, en de complete gids van CSS-Tricks blijft het nuttigste visuele cheatsheet. Voor productiegebruik is de browserondersteuning vrijwel universeel — geen voorvoegsels nodig. De W3C-specificatie is het doornemen waard als je ooit een echt verwarrend randgeval tegenkomt — het algoritme is nauwkeurig gedocumenteerd en beantwoordt de meeste "waarom gedraagt dit zich zo"-vragen.