What is Flexbox and Why It Matters
Flexbox (Flexible Box Layout) is a CSS layout model designed for arranging items in one dimension — either a row or a column. Before Flexbox, creating even simple layouts like a horizontal navigation bar or a vertically centered card required hacks involving floats, negative margins, or inline-block quirks. Flexbox solved these problems cleanly.
Today Flexbox is used in virtually every professional web project. Understanding it deeply — not just copying snippets — is one of the most high-leverage skills a frontend developer can have. It takes a few hours to learn and saves hundreds of hours over a career.
The Flex Container: Parent Properties
Flexbox works on a parent-child relationship. You declare a container as a flex container, and its direct children automatically become flex items. All the major layout decisions happen on the container.
.container {
display: flex; /* activates flexbox */
flex-direction: row; /* row | row-reverse | column | column-reverse */
flex-wrap: wrap; /* nowrap | wrap | wrap-reverse */
justify-content: center; /* alignment on main axis */
align-items: center; /* alignment on cross axis */
align-content: center; /* alignment of multiple lines */
gap: 16px; /* space between items */
}
flex-direction defines the main axis. row (default) runs left to right. column runs top to bottom. This single property changes the entire meaning of justify-content and align-items.
flex-wrap determines whether items must fit on one line or can wrap to the next. By default, items squeeze to fit on one line — setting flex-wrap: wrap lets them wrap naturally.
justify-content: Alignment on the Main Axis
justify-content controls how items are distributed along the main axis (horizontal for flex-direction: row).
| Value | Effect |
|---|---|
| flex-start | Items pack toward the start (default) |
| flex-end | Items pack toward the end |
| center | Items center along the axis |
| space-between | Equal space between items, none at edges |
| space-around | Equal space around each item |
| space-evenly | Equal space between items AND at edges |
space-between is the most commonly used value for navigation bars and card grids — it pushes items to the edges with equal spacing in between.
align-items: Alignment on the Cross Axis
align-items controls alignment on the cross axis (vertical when direction is row). This is the property that enables the famously simple vertical centering of Flexbox.
.container {
display: flex;
align-items: stretch; /* default — items fill container height */
/* align-items: center; — vertically centered */
/* align-items: flex-start; — aligned to top */
/* align-items: flex-end; — aligned to bottom */
/* align-items: baseline; — aligned by text baseline */
}
The default value, stretch, is why flex items often appear taller than their content — they're stretching to fill the container. Setting align-items: flex-start makes them only as tall as their content.
Flex Item Properties
Individual flex items can also have properties that override container-level settings.
.item {
flex-grow: 0; /* how much to grow relative to siblings (0 = don't grow) */
flex-shrink: 1; /* how much to shrink when space is tight */
flex-basis: auto; /* initial size before growing/shrinking */
/* Shorthand: flex: grow shrink basis */
flex: 1; /* shorthand for flex: 1 1 0 — grow to fill available space */
flex: 0 0 200px; /* fixed 200px width, no grow or shrink */
align-self: center; /* override align-items for just this item */
order: 2; /* change visual order without changing HTML order */
}
flex: 1 is one of the most powerful values in Flexbox — it tells an item to grow and take up all available space. If multiple items have flex: 1, they divide the space equally. This is how equal-width columns are created.
Common Flexbox Layout Patterns
Horizontal navigation bar:
nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
height: 64px;
}
Card grid that wraps:
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 24px;
}
.card {
flex: 1 1 280px; /* grows, shrinks, minimum 280px wide */
}
Sticky footer at the bottom of viewport:
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1; /* takes all remaining space, pushing footer down */
}