CSS Flexbox Visualized

Master CSS Flexbox from first principles — 11 interactive sections covering every property with live demos, real-world layouts, and a full playground.

By Forhad30 min readBeginnerInteractive Demo
CSS Flexbox Visualized

What is Flexbox?

CSS Flexbox (Flexible Box Layout) is a one-dimensional layout model that lets you distribute space among items in a container and align them — even when their size is unknown or dynamic. Before Flexbox, we relied on floats, inline-block hacks, and tables for layout. Those dark days are over.

Flexbox works along two axes: a main axis (set by flex-direction) and a cross axis (perpendicular to it). Every Flexbox property controls behavior along one of these two axes. Once you internalize this mental model, every property clicks into place.

The Mental Model: Two Axes

Imagine a horizontal line (→) and a vertical line (↓) inside your container. By default, the main axis runs left-to-right and the cross axis runs top-to-bottom. flex-direction can rotate these axes. Every other property — justify-content, align-items, etc. — just controls how items are distributed along one of these two axes.

The Two Axes

Every flexbox layout is built around these two perpendicular axes.

Main Axis (justify-content)
Cross Axis (align-items)
1
2
3
4

Container Properties

Applied to the parent: display, flex-direction, justify-content, align-items, flex-wrap, gap

Item Properties

Applied to children: flex-grow, flex-shrink, flex-basis, order, align-self

flex-direction

This is the first property you set — it defines the main axis of the container, which determines the direction flex items flow. Change it to column and suddenly justify-content controls vertical spacing and align-items controls horizontal alignment. The axes swap.

flex-direction

Controls the direction of the main axis — which way items flow inside the container.

Main
Cross
1
2
3
4
5

Current Value

row

Items flow left → right (default). Main axis is horizontal.

CSS

.container {
  display: flex;
  flex-direction: row;
}

💡 Tip: When you change flex-direction to column, justify-content now controls vertical alignment and align-items controls horizontal. The axes swap!

justify-content

Controls how items are distributed along the main axis. This is the property you'll use most often. The six values give you precise control over spacing — from packing items together to distributing them evenly across the container.

The three space-* values are the most powerful: space-between pushes items to the edges, space-around adds equal margins around each item, and space-evenlycreates perfectly uniform gaps everywhere.

justify-content

Distributes items along the main axis. Think of it as horizontal alignment when flex-direction is row.

flex-start
1
2
3
4
5
flex-end
1
2
3
4
5
center
1
2
3
4
5
space-between
1
2
3
4
5
space-around
1
2
3
4
5
space-evenly
1
2
3
4
5

flex-start

Items packed to the start of the main axis. This is the default.

|■ ■ ■ ■ |

CSS

.container {
  display: flex;
  justify-content: flex-start;
}

🎯 Real-world use: space-between is perfect for navbars (logo left, links right). center is ideal for centering a modal or card. space-evenly works great for icon toolbars.

align-items

While justify-content handles the main axis, align-items handles the cross axis. In a row layout, this means vertical alignment. The default value is stretch, which is why flex items automatically fill the container height — a behavior that surprises many beginners.

The baseline value is particularly useful when you have items with different font sizes and want their text to line up neatly.

align-items

Aligns items along the cross axis. In a row layout, this is vertical alignment.

Cross Axis ↕
Main Axis →
1
2
3
4
5

Current Value

stretch

Items stretch to fill the entire cross axis (default). All items become the same height in a row layout.

CSS

.container {
  display: flex;
  align-items: stretch;
  min-height: 200px;
}

🏆 Pro tip: The classic "center a div" problem? Just use display: flex; justify-content: center; align-items: center; on the parent. Done.

flex-wrap

By default, all flex items try to fit onto a single line (nowrap). This means items will shrink below their natural width if needed. Set flex-wrap: wrapand items that don't fit will flow onto the next line — essential for responsive card grids and tag lists.

flex-wrap

Controls whether items can wrap onto multiple lines or are forced into a single line.

1
2
3
4
5
6
7
8

nowrap

All items forced onto one line. Items will shrink to fit if needed, or overflow the container.

CSS

.container {
  display: flex;
  flex-wrap: nowrap;
}
.item {
  width: 100px;
}

⚡ Key insight: With nowrap, items shrink below their set width to fit. With wrap, items keep their width and flow to the next line. Try increasing item width above to see wrapping in action!

flex-grow, flex-shrink & flex-basis

These three item-level properties are the heart of Flexbox's space distribution. They answer three questions: How much should this item grow? (grow), How much should it shrink? (shrink), and What's its starting size? (basis).

The shorthand flex: 1 (which means flex: 1 1 0%) is the most common pattern — it makes items share space equally. flex: none (i.e., flex: 0 0 auto) makes an item rigid — it won't grow or shrink.

flex-grow, flex-shrink & flex-basis

The three item-level properties that control how items share space inside the container.

flex-grow

How much an item grows to fill extra space. 0 = don't grow. Higher number = more share.

flex-shrink

How much an item shrinks when there's not enough space. 0 = don't shrink.

flex-basis

The initial size before growing or shrinking. Like a starting width/height.

All items grow equally to fill the container.

1
1:1:0%
2
1:1:0%
3
1:1:0%

Item 1

flex-grow1
flex-shrink1
flex-basis0%

Item 2

flex-grow1
flex-shrink1
flex-basis0%

Item 3

flex-grow1
flex-shrink1
flex-basis0%

CSS

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

💡 Shorthand: flex: 1 is shorthand for flex: 1 1 0% (grow=1, shrink=1, basis=0%). flex: none means flex: 0 0 auto (fixed size, no growing or shrinking).

align-self

Sometimes you want one item to break away from the group. align-selflets a single item override the container's align-items value. It takes all the same values:flex-start, flex-end, center, stretch, baseline, plus auto (inherit from container).

align-self

Override the container's align-items for a single item. Click an item to change its individual alignment.

Container align-items:

Item 3

Set align-self for this item:

CSS

.container {
  display: flex;
  align-items: flex-start;
}
/* no align-self overrides */

order

The order property lets you rearrange items visually without touching the HTML. All items default to order: 0. Lower numbers appear first. You can use negative values to pull items before their siblings.

Important: This only changes visualorder. Screen readers and keyboard navigation still follow the HTML source order. Don't use it for meaningful content reordering.

order

Change the visual order of items without changing the HTML. Lower numbers appear first. Default is 0. Negative values are allowed.

HTML Order (source)

1
2
3
4
5

Visual Order (rendered)

1
2
3
4
5
Item 1order: 0
-5010

CSS

.item-1 { order: 0; }
.item-2 { order: 0; }
.item-3 { order: 0; }
.item-4 { order: 0; }
.item-5 { order: 0; }

⚠️ Accessibility warning: orderonly changes visual order, not tab/screen-reader order. Don't use it for meaningful content reordering — assistive tech follows the HTML source order.

gap

The gap property (originally from CSS Grid, now supported in Flexbox) adds space between items only — never at the container edges. This is cleaner than using margins, which require workarounds like negative margins on the container.

You can set row-gap and column-gap independently, or use the shorthandgap for both at once.

gap (row-gap & column-gap)

Controls spacing between flex items without adding margins. Cleaner than using margin on each item.

row-gap12px
column-gap12px
1
2
3
4
5
6
7
8
9

Gap vs Margin

gap: Space only between items, never at edges. Clean and predictable.

margin: Adds space around all items including edges. Needs hacks like negative margins on container.

CSS

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

Real-World Layout Patterns

Theory is great, but you came here to build real things. Here are six production-ready patterns that cover 90% of what you'll ever need with Flexbox. Each one is a pattern you'll reach for again and again — from navbars to card grids to the classic Holy Grail layout.

Real-World Layout Patterns

Six production-ready flexbox patterns you'll use every day. Click each to see it live with the CSS.

V
Brand
HomeAboutContact

🧭 Navbar

Logo left, navigation links right. The most common flexbox pattern on the web.

CSS

.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 24px;
  height: 60px;
}

Full Playground

Now combine everything you've learned. Toggle any container property, click individual items to customize their flex-grow, flex-shrink, flex-basis, order, and align-self. The generated CSS updates live — copy it straight into your project.

Full Playground

Combine every property. Click items to customize individually.

flex-direction
justify-content
align-items
flex-wrap
gap8px
items5
Generated CSS
.container {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: stretch;
  flex-wrap: nowrap;
  gap: 8px;
}