CSS Flexbox: A Complete Guide With Live Examples

IPS Inc.

–

September 28, 2026

Home » Web Development » CSS Flexbox: A Complete Guide With Live Examples
CSS Flexbox guide with live examples of justify-content, align-items and flex: 1 layouts
Three of the live flexbox examples from this guide: justify-content, align-items and flex: 1.

CSS flexbox is the layout tool for putting things in a row or a column and controlling how they share the space. It handles alignment, spacing, reordering and wrapping with a few properties, and every current browser supports it.

This guide covers every flexbox property, on the container and on the items, with a live example for each value. The examples are real flexbox drawn by your browser, so what you see is exactly what the code does. After the properties come the layouts people build most often, and the bugs people hit most often, with the fix for each.

Short on time? This one-minute video walks through the core properties, then the guide covers each one in detail.

A silent 60-second walkthrough: display, justify-content, align-items, flex-direction, flex-grow and flex-wrap. Every layout in it is real flexbox, measured in a browser.

Key Takeaways

  • Flexbox lays items out in one direction at a time: a row or a column. For rows and columns at once, use CSS Grid.
  • Put display: flex on the parent. Everything else is either a container property or an item property.
  • justify-content works along the main axis; align-items works across it. Which way is which depends on flex‑direction.
  • flex: 1 means grow, shrink and start from zero. It gives equal widths only when the items have no padding or content that forces them wider.
  • Most “flexbox is broken” moments come from one default: flex items will not shrink below their content. min-width: 0 fixes it.

What Is CSS Flexbox?

Flexbox, short for the Flexible Box Layout module, is a CSS layout mode for arranging items along a single line. MDN describes it as “a one-dimensional layout model for distributing space between items and includes numerous alignment capabilities”.

You turn it on with one line on the parent element. Its direct children then become flex items and line up in a row:

.container {
  display: flex;
}
1
2
3
display: flex The three children sit in a row, side by side.

The Two Axes: Main and Cross

Every flexbox property works along one of two axes. MDN puts it this way: “The main axis is defined by the flex-direction property, and the cross axis runs perpendicular to it.”

In the default row layout, the main axis runs left to right and the cross axis runs top to bottom. Switch to a column and they swap: the main axis runs top to bottom.

Term What it means
Flex container the element with display: flex
Flex items its direct children (grandchildren are not affected)
Main axis the direction items are laid out in, set by flex‑direction
Cross axis the direction at right angles to the main axis
Main start, main end where the first and last item sit on the main axis

This is the one idea to hold on to. justify-content always means “along the main axis” and align-items always means “along the cross axis”, whichever way the axes point.

Properties for the Flex Container

These go on the parent, the element with display: flex.

display

display: flex makes the element a block-level flex container: it takes the full width available, like a div. display: inline-flex makes an inline-level one that is only as wide as its contents and sits in a line of text.

1
2
3
display: inline-flex The container shrinks to fit its items.

flex-direction

flex-direction sets the main axis, and with it the direction the items flow. The initial value is row.

1
2
3
flex‑direction: row
1
2
3
flex-direction: row-reverse Right to left, starting at the right edge.
1
2
3
flex‑direction: column
1
2
3
flex‑direction: column‑reverse

The reverse values change only what you see, not the order in the HTML. Screen readers and the Tab key still follow the source order, so use them for visual effect only (more on this under order).

flex-wrap

By default, flex items all stay on one line and shrink to fit. flex-wrap lets them wrap onto new lines instead. The initial value is nowrap.

1
2
3
4
5
6
flex-wrap: nowrap Six items each asked to be 35% wide are squeezed onto one line.
1
2
3
4
5
6
flex-wrap: wrap Each item keeps its 35% width, and the rest move to the next line.
1
2
3
4
5
6
flex-wrap: wrap-reverse Lines stack from the bottom up.

flex-flow

flex-flow is shorthand for flex-direction and flex-wrap together. The initial value is row nowrap.

.container {
  flex-flow: row wrap; /* same as flex-direction: row; flex-wrap: wrap; */
}

justify-content

justify-content distributes the items, and the free space between them, along the main axis. The initial value is normal, which in a flex container packs the items at the start.

1
2
3
justify‑content: flex‑start
1
2
3
justify‑content: flex‑end
1
2
3
justify‑content: center
1
2
3
justify-content: space-between First and last items touch the edges; the space is shared between them.
1
2
3
justify-content: space-around Each item gets equal space on both sides, so the gaps at the edges are half the gaps between items.
1
2
3
justify-content: space-evenly Every gap is the same, including the two at the edges.

You will also see start and end. In a normal left-to-right row they look the same as flex-start and flex-end; the difference shows with reversed directions, where start follows the writing direction and flex-start follows the flex direction.

align-items

align-items places the items along the cross axis, inside their line. The initial value is normal, which in a flex container stretches the items to fill the line. The items below have different amounts of content, so you can see the difference.

1
2
3
align-items: stretch Every item is as tall as the container.
1
2
3
align‑items: flex‑start
1
2
3
align‑items: flex‑end
1
2
3
align‑items: center
1
2
3
align-items: baseline The first lines of text line up, whatever the item sizes.

Stretching only happens to items with no fixed size on the cross axis. Give an item a height in a row, and stretch leaves it at that height.

align-content

align-content spaces the lines of a wrapping container along the cross axis, the way justify-content spaces items along the main axis. It does nothing unless the items wrap onto more than one line and the container has spare room across. The initial value is normal, which stretches the lines.

1
2
3
4
5
6
align-content: stretch The two lines share the full height.
1
2
3
4
5
6
align‑content: flex‑start
1
2
3
4
5
6
align‑content: center
1
2
3
4
5
6
align‑content: space‑between

align-content also takes flex-end, space-around and space-evenly, which work like their justify-content versions, turned through 90 degrees.

gap, row-gap and column‑gap

gap puts fixed space between items without adding space at the outer edges. One value sets both directions; two values set the row gap and then the column gap.

1
2
3
4
5
6
gap: 16px
1
2
3
4
5
6
gap: 24px 8px 24px between lines, 8px between items in a line.

gap replaces the old trick of margins on every item and a negative margin on the container. It is well supported in flex layouts: according to MDN’s compatibility data it arrived in Chrome 84, Firefox 63 and Safari 14.1.

Properties for the Flex Items

These go on the children of the flex container.

order

order changes where an item appears without moving it in the HTML. Items are laid out from the lowest order to the highest, and the initial value is 0.

1
2
3
.item-1 { order: 1; } Item 1 moves to the end, because the others are still order 0.

Use it sparingly. The spec is blunt: authors must not use order or the -reverse directions “as a substitute for correct source ordering, as that can ruin the accessibility of the document.” Keyboard focus and screen readers follow the HTML, so a visual reorder can make the Tab key jump around the page.

flex-grow

flex-grow says how much of the leftover space an item takes. The initial value is 0, so items do not grow unless you ask them to.

1
2
3
.item-2 { flex-grow: 1; } Item 2 takes all the free space.
1
2
3
flex-grow: 1, 2 and 1 Item 2 gets twice as much of the free space as each of the others.

The key word is free space. flex-grow: 2 does not make an item twice as wide as the others; it gives it twice their share of whatever space is left after every item has its starting size.

flex-shrink

flex-shrink says how much an item gives up when there is not enough room. The initial value is 1, so every item shrinks by default; 0 stops an item shrinking.

1
2
3
.item-2 { flex-shrink: 0; } All three ask for 60%, which cannot fit. Item 2 keeps its 60% and the other two give up the difference.

Items never shrink below their minimum content size, which is usually their longest word. That limit causes most flexbox overflow bugs, covered below.

flex-basis

flex-basis sets an item’s starting size on the main axis, before any growing or shrinking. The initial value is auto, which means “use my width, or my content if I have no width”.

1
2
3
.item-1 { flex-basis: 50%; } Item 1 starts at half the row.

The difference between auto and 0 matters when items also grow. With flex-basis: auto, the free space is shared out on top of each item’s content, so longer content ends up wider. With flex-basis: 0, the items start from nothing and the free space is the whole row.

A
Longer label
B
flex: 1 1 auto Same growth, but the longer label stays wider.
A
Longer label
B
flex: 1 1 0 Starting from zero, all three end up the same width.

flex (the shorthand)

flex sets flex-grow, flex-shrink and flex-basis in one go, and it is the form you will use most. The spec lists four values that cover most needs:

You write It means What it does
flex: initial 0 1 auto the default: sized by width or content, can shrink, will not grow
flex: auto 1 1 auto sized by width or content, then grows and shrinks to fill the line
flex: none 0 0 auto fixed at its width or content size: never grows, never shrinks
flex: 1 (any positive number) 1 1 0 starts from zero and takes that share of the space

Those equivalents come straight from the W3C flexbox specification, which describes flex: <number> as making “the flex item flexible and sets the flex basis to zero”. The spec also recommends the shorthand over the separate properties, because it resets the parts you do not mention to sensible values.

align-self

align-self overrides align-items for one item. The initial value is auto, which means “use the container’s align‑items”.

1
2
3
align-self: flex-end and center The container says flex-start; items 2 and 3 override it.

Auto margins

An auto margin on a flex item takes up all the free space on that side. It is the simplest way to push one item away from the rest.

1
2
3
.item-3 { margin-left: auto; } Item 3 is pushed to the far end.

Auto margins also beat justify-content: when an item has one, there is no free space left for justify-content to share out. Flex item margins behave differently from block margins in one more way: “The margins of adjacent flex items do not collapse.”

Common Flexbox Layouts

These are the patterns that come up on nearly every site. Each one is only a few lines.

Center Anything, Horizontally and Vertically

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 160px;
}
Centred
justify-content: center with align-items: center on the same container.
.nav { display: flex; align-items: center; gap: 8px; }
.nav .first-link { margin-left: auto; }
Logo
Home
Contact
.first-link { margin-left: auto; } The first link takes the free space on its left, so the links move to the right.

Equal-Height Cards

Cards in a row are the same height by default, because align-items stretches them. Give each card flex: 1 and they share the width too.

Short
A card with a lot more text that runs onto several lines
Medium length
.card { flex: 1 1 0; min-width: 0; }

To keep each card’s button at the bottom whatever the text length, make the card itself a column and push the button down:

.card { display: flex; flex-direction: column; }
.card .button { margin-top: auto; }

An Input With a Button Beside It

.form-row { display: flex; gap: 8px; }
.form-row input { flex: 1; min-width: 0; }
Email address
Subscribe
input { flex: 1; min-width: 0; }

A Sidebar and Main Content

.layout { display: flex; gap: 8px; }
.sidebar { flex: 0 0 30%; }
.main { flex: 1; min-width: 0; }
Sidebar
Main content
.sidebar { flex: 0 0 30%; } .main { flex: 1; }

On small screens, switch the container to flex-direction: column in a media query and the sidebar sits above the content.

A Wrapping Row of Cards

.cards { display: flex; flex-wrap: wrap; gap: 8px; }
.cards > * { flex: 1 1 110px; }
1
2
3
4
5
6
7
flex: 1 1 110px Each card starts at 110px and grows to fill its line, so the card left alone on the last line grows wider than the rest.

That last line is the trade-off of a flexbox grid. If every card must be the same width, CSS Grid is the better tool.

Common Flexbox Problems and How to Fix Them

We tested each of these in the browser before writing it down.

Text or Content Overflows a Flex Item

A flex item will not shrink below its content. The spec calls this the automatic minimum size: by default, it is the item’s “content-based minimum size”, which is usually its longest word or its widest child.

So a long URL, a wide table or a pre block inside a flex item pushes the whole row wider than its container. The fix is to let the item shrink:

.item {
  min-width: 0;             /* allow the item to shrink below its content */
  overflow-wrap: anywhere;  /* and let long words break */
}

In a column, the same limit applies to height, and the fix is min‑height: 0.

flex: 1 Items Are Not the Same Width

flex: 1 shares out the space, but padding, borders and content still come first. In our test, two flex: 1 items in a 300px row came out at 110px and 190px, because the second had 80px of padding.

Two fixes, depending on the cause:

  • If content is forcing it, add min-width: 0 to the items, as above.
  • If padding is forcing it, set the widths directly instead, for example flex: 0 0 50% with box-sizing: border-box, or use CSS Grid with grid-template-columns: 1fr 1fr.

Images Stretch or Look Squashed

align-items stretches items by default, and an image is an item like any other. In our test, an image with no height attribute, next to a 200px-tall block, was stretched from 80px to 200px tall.

Any one of these stops it:

.container { align-items: flex-start; } /* or center */
/* or */
img { align-self: flex-start; }

Adding the height attribute to the img tag, as you should for layout stability anyway, also stopped the stretch in our test.

text-overflow: ellipsis Does Nothing

The ellipsis has to go on the element that holds the text, not on the flex container. MDN lists text-overflow as applying to “block container elements”, and a flex container is not one.

.item {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

The Last Row Spreads Out With space-between

With flex-wrap: wrap and justify-content: space-between, a short last row spreads its items to the two edges and leaves a hole in the middle. Use gap with the default justify-content instead, or switch to CSS Grid if the items must line up in columns.

Margins Do Not Collapse

In normal block layout, the bottom margin of one element and the top margin of the next merge into one. In flexbox they add up: our test with 20px and 20px gave a 40px gap. If spacing looks doubled after switching to flexbox, set the margin on one side only, or replace the margins with gap.

Tab Order Jumps Around

If you used order or a -reverse direction, keyboard users still move through the items in HTML order. Change the HTML instead, and keep visual reordering for things that are not interactive.

Flexbox vs Grid: Which Should You Use?

Use flexbox when you are arranging things in one line, and Grid when you need rows and columns to line up with each other. MDN puts the difference in one sentence: “Flexbox is a one-dimensional layout method whereas grid layout is a two-dimensional layout method.”

Use flexbox for Use Grid for
navigation bars, toolbars, button groups page layouts with header, sidebar, content and footer
centring one thing inside another card grids where every column must line up
a row of items whose sizes come from their content layouts where the columns set the sizes
components that stack into a column on mobile overlapping items and named areas

They are not rivals. A common pattern is Grid for the page and flexbox inside each component.

Is Flexbox Supported in All Browsers?

Yes. MDN marks flexbox as widely available: “It’s been available across browsers since September 2015.” You do not need vendor prefixes for any current browser.

The one newer piece is gap in flex layouts, supported since Chrome 84, Firefox 63 and Safari 14.1.

Flexbox Cheat Sheet

Property Set on Common values Initial value
display container flex, inline‑flex not flex
flex-direction container row, row-reverse, column, column‑reverse row
flex-wrap container nowrap, wrap, wrap‑reverse nowrap
flex-flow container row wrap and similar row nowrap
justify-content container flex-start, center, space-between, space‑around, space‑evenly normal (packs at the start)
align-items container stretch, flex-start, center, flex‑end, baseline normal (stretches)
align-content container stretch, flex-start, center, space‑between normal (stretches lines)
gap container 16px, 24px 8px normal (no gap)
order item any whole number 0
flex-grow item 0, 1, 2 0
flex-shrink item 0, 1 1
flex-basis item auto, 0, 200px, 50% auto
flex item 1, auto, none, 0 0 200px 0 1 auto
align-self item auto, flex-start, center, flex‑end, stretch auto

Building fluid type to go with your flex layouts? Our guide to CSS clamp() for fluid typography covers font sizes that scale with the screen.

Need Help With a Layout?

If a layout is fighting you, or you would rather have it built properly the first time, our web design team builds responsive sites with clean, maintainable CSS.

FAQs

What Is the Difference Between justify-content and align‑items?

justify-content positions items along the main axis, and align-items positions them along the cross axis. In a row, that is horizontal and vertical; in a column, it is the other way round.

What Does flex: 1 Mean?

It is short for flex: 1 1 0: the item can grow, can shrink, and starts from a size of zero. Items with flex: 1 share the space equally, unless padding or content forces one wider.

How Do You Center a Div With Flexbox?

Put display: flex, justify-content: center and align-items: center on its parent. The parent needs a height taller than the child for the vertical centring to show.

Why Is My Flex Item Overflowing Its Container?

Because flex items will not shrink below their content by default. Add min-width: 0 to the item, and overflow-wrap: anywhere if long words or URLs are the cause.

Should I Use Flexbox or Grid?

Use flexbox for one line of items and Grid for rows and columns together. Many layouts use both: Grid for the page, flexbox inside each part of it.

Laptop balanced on a hand showing a website design

What We Offer

Ready to solve
your next challenge?

Browse the full range of services we deliver, from branding to ongoing maintenance.

Laptop balanced on a hand showing a website design

Next step

Planning a site like this? Let’s scope it together.

Tell us what the site has to do. We map the pages, the platform and the budget with you before any work starts, and we coordinate on your working hours.

What happens next

Explore More 

Related Blogs.