Skip to main content

Flexbox in Practice: flex-direction, justify-content, and align-items Made Visual

A practical flexbox walkthrough — set the axis with flex-direction, distribute space with justify-content, center with align-items, handle wrap, and copy the generated CSS instantly.

Published By 李雷
#flexbox #css #frontend #layout

Flexbox in Practice: flex-direction, justify-content, and align-items Made Visual

Flexbox has been the default way to lay out a row of cards, a navbar, or a centered hero for years now, yet I still catch myself second-guessing which axis justify-content controls. The properties are not hard; the trouble is that they all interact, and reading three of them in your head rarely matches what the browser actually paints. The fastest cure is to stop guessing and watch a real display: flex box react as you change one value at a time. That is exactly what the Flexbox Playground & CSS Generator does, and below I'll walk through the four properties that cover roughly 90% of real layouts.

flex-direction sets the main axis — everything else follows it

Before anything else, decide your main axis. flex-direction: row (the default) lays items left to right, so the main axis is horizontal and the cross axis is vertical. flex-direction: column flips that: items stack top to bottom, the main axis becomes vertical, and the cross axis is horizontal. There are also row-reverse and column-reverse, which run the same axis backwards.

This single choice is load-bearing because justify-content always works along the main axis and align-items always works along the cross axis. Switch from row to column and those two properties effectively swap which direction they push things. If you ever set justify-content: center expecting vertical centering and nothing moves, the real problem is almost always that you are in a row and centering horizontally instead. Toggle the direction in the playground and watch which axis the items slide along — that visual cue tells you which property you actually need.

justify-content distributes free space along the main axis

Once the axis is set, justify-content decides what to do with leftover space on it. There are six values worth knowing:

  • flex-start / flex-end — pack items at the start or end.
  • center — pack them in the middle.
  • space-between — first and last items hug the edges, equal gaps between the rest.
  • space-around — equal space around each item (so edge gaps are half the size of inner gaps).
  • space-evenly — truly equal gaps, including the edges.

The space-between versus space-around versus space-evenly distinction is the one most people fumble, because describing it in words is genuinely worse than seeing it. Drop a few items in the preview and cycle through all three; the difference clicks in about two seconds.

One catch to internalize: justify-content only has anything to do when there is free space to distribute. If every child has flex-grow: 1 (or flex: 1), the items already fill the whole main axis, so every justify-content value renders identically. Per MDN's flexbox documentation, justify-content aligns along the main axis and applies to the free space after item sizing — which is why "my justify-content isn't doing anything" usually means "there's no free space left."

align-items handles the cross axis (and yes, this is how you center)

align-items aligns items along the cross axis. Its common values are stretch (the default — items grow to fill the cross dimension), flex-start, flex-end, center, and baseline.

The famous "center a div both ways" task is just these two properties together. In a row container, set justify-content: center to center horizontally and align-items: center to center vertically, leave one item in the box, and it sits dead-center. Here is what the generator emits for that case:

.container {
  display: flex;
  justify-content: center;
  align-items: center;
}

That is the entire modern replacement for the old position: absolute; transform: translate(-50%, -50%) hack — no magic numbers, no fixed dimensions, and it survives content changes. The generator only outputs the properties you actually changed, so defaults like flex-direction: row stay out of the result and you get a clean, paste-ready rule.

flex-wrap and align-content: the multi-line story

By default a flex container is single-line: flex-wrap: nowrap forces every item onto one line, shrinking them if needed. Set flex-wrap: wrap and items that don't fit spill onto a new line — perfect for a tag list, a gallery, or a responsive card grid.

Wrapping unlocks align-content, the property that trips up the most people. align-content aligns the flex lines relative to each other along the cross axis, and you only have multiple lines once items wrap. On a nowrap container there is exactly one line, so align-content does literally nothing. Keep the roles straight: align-items aligns items within a line, align-content spaces the lines apart. The playground disables the align-content control entirely until you turn on wrap, which means you learn the dependency by doing rather than by debugging a value that silently has no effect.

If you find yourself reaching for two-dimensional row-and-column control rather than a single flowing axis, that is the signal to switch tools — flexbox is one-dimensional by design, and a dedicated CSS grid generator is the better fit for explicit rows and columns.

A worked example: equal-width cards from grow, shrink, and basis

Here is the moment flexbox stops feeling like guesswork for me. I needed three pricing cards that stay exactly one-third wide even though one card had noticeably more copy than the others. I added three items, selected each one in the preview, and set flex-grow: 1, flex-shrink: 1, flex-basis: 0%. The generator recognized that combination and collapsed it to the shorthand automatically:

.container {
  display: flex;
}
.item-1, .item-2, .item-3 {
  flex: 1;
}

The key is flex-basis: 0% (the 0 in flex: 1). It tells each item to start from zero width and then take a share of the container proportional to its grow factor — which is why three children all set to flex: 1 end up perfectly equal regardless of content length. This is different from flex: auto (1 1 auto), where each item starts from its content size and only then splits the remainder, so cards with different text drift to different widths. If your "equal" columns ever creep apart, you almost certainly used auto where you wanted 1.

Copy the CSS — and share the exact layout

The whole point of treating this as a generator, not just a sandbox, is the output. Every control round-trips through the URL, so the link you copy lands a teammate on the identical layout, and the CSS panel only emits the properties you changed — no noisy default values to delete. Build a navbar by giving the logo flex-grow: 1 to push the links right, reorder an item with order: -1 without touching the DOM, or test how a wrapped gallery spaces its rows, then copy a rule you can paste straight into your stylesheet. Open the Flexbox Playground & CSS Generator, change one property, and watch the box move — it is a faster teacher than any cheat sheet.


Made by Toolora · Updated 2026-06-13