Flexbox: One-Dimensional Layout
Flexbox arranges children of a container along a single line - a row or a column. That's the whole premise: one dimension at a time. It's the right tool anytime you're thinking "put these things next to each other" or "stack these and space them out."
Turning it on
One property starts it:
}
Every direct child of .navbar is now a flex item. By default they line up in a row, left to
right, each sized to its own content - no floats, no inline-block, no clearfix.
Main axis vs cross axis
Flexbox thinks in two axes, and almost every property is "along the main axis" or "along the cross axis":
- Main axis - the direction items flow. Row by default (left to right). Set
flex-direction: columnto flow top to bottom instead, which swaps which axis is "main." - Cross axis - perpendicular to the main axis. Row layout → cross axis is vertical. Column layout → cross axis is horizontal.
flex-direction: row (default)
┌─────────────────────────────┐
│ [Item] [Item] [Item] → │ ← main axis (horizontal)
│ ↕ cross axis (vertical) │
└─────────────────────────────┘
Once that clicks, justify-content and align-items stop being two properties to memorize and become
one idea applied twice.
Positioning items: justify-content and align-items
justify-content- spacing along the main axis:flex-start,center,flex-end,space-between,space-around.align-items- alignment along the cross axis:flex-start,center,flex-end,stretch(default).
}
What just happened: in a row layout, justify-content controls left-right spacing and
align-items controls up-down alignment. space-between is what makes "logo left, links right" a
one-line fix instead of a positioning puzzle.
💡 Key point. "Center a div" - the CSS joke for a decade - is two lines:
}
align-self overrides align-items for one specific item, when everyone else stays aligned one
way and a single item needs to sit differently:
}
Build it: a real navbar
The logo-left, links-right navbar, done properly:
Acme
Home
Docs
About
}
}
What just happened: the outer .navbar flex container pushes .logo and .nav-links to opposite
ends and centers them vertically. The inner .nav-links is also a flex container, laying its <li>s
out in a row with gap for spacing - no margin math, no :last-child { margin-right: 0 } cleanup.
Flex containers nest freely; each one only manages its own children.
Wrapping: flex-wrap
By default, flex items shrink to fit on one line, however cramped that gets. flex-wrap: wrap lets
them drop to a new line instead:
}
Without flex-wrap, five cards in a narrow viewport squeeze into an unreadable sliver. With it, cards
that don't fit flow onto the next row, like text wrapping at the edge of a paragraph.
Sizing items: flex-grow, flex-shrink, flex-basis
Three properties control how an item's size responds to available space, almost always used through
the flex shorthand (flex-grow flex-shrink flex-basis):
flex-grow- how much of the leftover space this item claims, relative to siblings.0(default) means it won't grow.flex-shrink- how much this item shrinks when there isn't enough space.1(default) means it shrinks proportionally.flex-basis- the item's starting size before growing/shrinking, likewidthbut flex-aware.
Build it: a row of equal-width cards
Card 1
Card 2
Card 3
}
}
What just happened: flex: 1 is shorthand for flex-grow: 1; flex-shrink: 1; flex-basis: 0%. Each
card starts at zero width, then grows to fill the row equally - three cards, three equal thirds,
recalculated automatically whether you have three cards or five. Change one card to flex: 2 and it
claims twice the leftover space of its siblings; a common pattern for a "featured" card that's wider
than the rest.
⚠️ Gotcha. flex: 1 and width: 33% look similar but behave differently on resize: percentage
widths are fixed fractions of the container, while flex: 1 items renegotiate space with their
siblings every time one shrinks, grows, or wraps. For equal-width items in a flex row, flex: 1 is the
right tool - it rebalances space instead of dividing it once and freezing.
Check your intuition with a quick quiz:
[
{
"q": "In a default (row) flex container, what does justify-content control?",
"choices": ["Vertical alignment", "Horizontal spacing along the main axis", "The stacking order of items", "The font size of items"],
"answer": 1,
"explain": "justify-content works along the main axis, which is horizontal in a row layout. align-items handles the cross (vertical) axis."
},
{
"q": "Three items each have flex: 1 in a flex row. What happens if you change one to flex: 2?",
"choices": ["It disappears", "It becomes exactly twice as wide in pixels, always", "It claims roughly twice the leftover space of its siblings", "Nothing, flex-grow is ignored without flex-basis set separately"],
"answer": 2,
"explain": "flex-grow values are compared as ratios among siblings sharing the leftover space, not absolute sizes."
},
{
"q": "Your flex row of five cards is unreadable on a narrow screen because they're all squeezed onto one line. What fixes it?",
"choices": ["flex-direction: column-reverse", "flex-wrap: wrap", "justify-content: space-around", "align-self: stretch"],
"answer": 1,
"explain": "flex-wrap: wrap lets items that don't fit flow onto a new line instead of shrinking indefinitely."
}
]
Guide overview · Phase 2: CSS Grid: Two-Dimensional Layout →
Check your understanding 3 questions
1. In a default (row) flex container, what does justify-content control?
2. Three items each have flex: 1 in a flex row. What happens if you change one to flex: 2?
3. Your flex row of five cards is unreadable on a narrow screen because they're all squeezed onto one line. What fixes it?