CSS Flexbox Explained -- Properties, Alignment, and Common Layout Patterns

Learn how CSS Flexbox works, from container and item properties to six practical layout patterns you can use immediately.

The Quick Answer

CSS Flexbox is a one-dimensional layout model that distributes space among items in a container and aligns them along a main axis and a cross axis.

Set display: flex on a container, and its direct children become flex items that you can align, space, stretch, and reorder using a small set of properties.

.container {
  display: flex;
  justify-content: center;  /* main axis alignment */
  align-items: center;       /* cross axis alignment */
  gap: 1rem;                 /* space between items */
}

Try different property combinations in our Flexbox Playground to see results in real time.

How Flexbox Works: Two Axes

Every flex container has two axes:

  • Main axis -- the direction flex items are placed in. Default is horizontal (left to right).
  • Cross axis -- perpendicular to the main axis. Default is vertical (top to bottom).
flex-direction: row (default)

Main axis:   ------>
Cross axis:  |
             v

flex-direction: column

Main axis:   |
             v
Cross axis:  ------>

Understanding which axis is which determines how justify-content and align-items behave. justify-content always works on the main axis. align-items always works on the cross axis.

Container Properties

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

flex-direction

Controls the main axis direction.

Value Main Axis Items Flow
row (default) Horizontal Left to right
row-reverse Horizontal Right to left
column Vertical Top to bottom
column-reverse Vertical Bottom to top

flex-wrap

Controls whether items wrap to new lines.

Value Behavior
nowrap (default) All items stay on one line; they shrink to fit
wrap Items wrap to the next line when they overflow
wrap-reverse Items wrap upward instead of downward

justify-content

Aligns items along the main axis.

Value Effect
flex-start (default) Pack items to the start
flex-end Pack items to the end
center Center items
space-between Equal space between items; no space at edges
space-around Equal space around each item (half-space at edges)
space-evenly Equal space between items and at edges

align-items

Aligns items along the cross axis.

Value Effect
stretch (default) Items stretch to fill the container's cross size
flex-start Align to the start of the cross axis
flex-end Align to the end of the cross axis
center Center on the cross axis
baseline Align items by their text baselines

align-content

Controls spacing of wrapped lines along the cross axis. Only applies when flex-wrap: wrap is set and there are multiple lines. Accepts the same values as justify-content plus stretch.

gap

Sets the spacing between flex items. Accepts one value (both axes) or two values (row-gap and column-gap).

.container {
  display: flex;
  gap: 1rem;         /* 1rem between all items */
  gap: 1rem 2rem;    /* 1rem row gap, 2rem column gap */
}

gap is supported in all modern browsers for Flexbox since 2021. It replaces the older workaround of using margins on items. See MDN: gap.

Item Properties

These properties go on the flex items (direct children of the flex container).

flex-grow

Controls how much an item grows relative to siblings when extra space is available. Default is 0 (do not grow).

.item-a { flex-grow: 1; }  /* gets 1 share of extra space */
.item-b { flex-grow: 2; }  /* gets 2 shares of extra space */

If the container has 300px of extra space, item-a gets 100px and item-b gets 200px.

flex-shrink

Controls how much an item shrinks relative to siblings when space is insufficient. Default is 1 (shrink equally).

Setting flex-shrink: 0 prevents an item from shrinking below its basis.

flex-basis

Sets the initial size of an item before growing or shrinking. Default is auto (uses the item's width or content size).

.item { flex-basis: 200px; }  /* starts at 200px, then grows/shrinks */

In a row layout, flex-basis acts like width. In a column layout, it acts like height. When both flex-basis and width are set, flex-basis takes priority.

The flex Shorthand

The flex shorthand sets flex-grow, flex-shrink, and flex-basis in one declaration.

Shorthand Expands To Meaning
flex: 0 1 auto grow:0, shrink:1, basis:auto Default behavior
flex: 1 grow:1, shrink:1, basis:0% Grow to fill space equally
flex: auto grow:1, shrink:1, basis:auto Grow from content size
flex: none grow:0, shrink:0, basis:auto Fixed size, no flex
flex: 0 0 200px grow:0, shrink:0, basis:200px Fixed at 200px

Note that flex: 1 sets the basis to 0%, not auto. This is important: it means the item ignores its content size when distributing space, so all flex: 1 items get equal widths regardless of content. This catches many people off guard. See W3C Flex Shorthand specification.

align-self

Overrides align-items for a single item. Accepts the same values.

.container { align-items: flex-start; }
.special-item { align-self: center; }  /* only this item is centered */

order

Changes the visual order of an item. Default is 0. Lower values appear first.

.item-first { order: -1; }  /* appears before order: 0 items */
.item-last { order: 1; }    /* appears after order: 0 items */

Note: order only changes visual order, not tab order or screen reader order. Use with care for accessibility.

Six Common Layout Patterns

Pattern 1: Centering an Element (Both Axes)

.center-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}
<div class="center-container">
  <div class="centered-content">Centered</div>
</div>

The container needs a defined height for vertical centering to work. min-height: 100vh makes it fill the viewport.

Pattern 2: Navigation Bar (Logo Left, Links Right)

.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 2rem;
}
<nav class="navbar">
  <div class="logo">Site Name</div>
  <ul class="nav-links">
    <li><a href="/">Home</a></li>
    <li><a href="/about">About</a></li>
    <li><a href="/contact">Contact</a></li>
  </ul>
</nav>

space-between pushes the logo and links to opposite ends. align-items: center vertically centers them.

Pattern 3: Equal-Width Columns

.columns {
  display: flex;
  gap: 1rem;
}
.columns > * {
  flex: 1;
}
<div class="columns">
  <div>Column 1</div>
  <div>Column 2</div>
  <div>Column 3</div>
</div>

flex: 1 on each child gives them equal shares of the container width, regardless of content length.

Pattern 4: Sticky Footer Layout

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  margin: 0;
}
main {
  flex: 1;
}
<body>
  <header>Header</header>
  <main>Content</main>
  <footer>Footer</footer>
</body>

The main element grows to fill all available vertical space, pushing the footer to the bottom even when content is short.

Pattern 5: Card Grid with Wrapping

.card-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}
.card {
  flex: 0 1 calc(33.33% - 0.67rem);
}
<div class="card-grid">
  <div class="card">Card 1</div>
  <div class="card">Card 2</div>
  <div class="card">Card 3</div>
  <div class="card">Card 4</div>
  <div class="card">Card 5</div>
</div>

Each card takes roughly one-third of the container width (minus gap space). When the viewport narrows, cards wrap to the next row. The calc value accounts for the gap: with 3 items per row and 2 gaps, each item subtracts 2/3 of the gap size.

Pattern 6: Sidebar + Main Content

.layout {
  display: flex;
  gap: 2rem;
}
.sidebar {
  flex: 0 0 250px;  /* fixed width, no grow, no shrink */
}
.main-content {
  flex: 1;           /* fills remaining space */
}
<div class="layout">
  <aside class="sidebar">Sidebar</aside>
  <div class="main-content">Main</div>
</div>

The sidebar stays at 250px. The main content area fills the rest. Add min-width: 0 to .main-content if long words or wide elements cause overflow issues.

Common Mistakes

Not accounting for min-width

By default, flex items will not shrink below their minimum content size (the length of the longest word or widest child element). If an item refuses to shrink, add:

.item { min-width: 0; }

This allows the item to shrink below its content size. For column layouts, use min-height: 0 instead.

Confusing flex-basis with width

When both are set, flex-basis wins in a flex context. Setting width: 200px on a flex item and then flex-basis: 300px results in a starting size of 300px. Use one or the other, not both, to avoid confusion.

Forgetting that flex: 1 sets basis to 0%

flex: 1 means flex: 1 1 0%. The item's content size is ignored for space distribution. If you want items to grow from their content size, use flex: auto (which is flex: 1 1 auto) instead.

Using Flexbox when Grid is more appropriate

If you need items to align in both rows and columns simultaneously (like a data table or a two-dimensional grid), CSS Grid gives you direct control over both axes. Flexbox is one-dimensional -- it excels at distributing items along a single axis.

Experiment with Flexbox

Flexbox Playground

Adjust every flex container and item property and see the results in real time. Includes presets for common layout patterns.

Open Flexbox Playground

Frequently Asked Questions

When should I use Flexbox vs CSS Grid?

Use Flexbox for one-dimensional layouts (a single row or column of items). Use Grid for two-dimensional layouts (rows and columns simultaneously). Flexbox is ideal for navigation bars, card rows, and centering. Grid is better for full page layouts and arrangements where you need control over both axes at once. The two work well together -- a Grid layout can contain Flexbox components.

How do I center a div with Flexbox?

Set the parent container to display: flex; justify-content: center; align-items: center. This centers the child both horizontally and vertically. The parent needs a defined height (e.g., min-height: 100vh) for vertical centering to be visible.

What does flex: 1 mean?

flex: 1 is shorthand for flex-grow: 1, flex-shrink: 1, flex-basis: 0%. It tells the item to grow and fill available space equally with other flex: 1 items. The 0% basis means sizing starts from zero, so all items get equal shares regardless of their content size.

How do I make flex items equal width?

Set flex: 1 on each item. This makes every item start from a 0% basis and grow equally. Alternatively, set flex-basis to a percentage like 33.33% for three columns, combined with flex-grow: 0 to prevent unequal growth.

What is the difference between justify-content and align-items?

justify-content controls alignment along the main axis (horizontal in a row layout, vertical in a column layout). align-items controls alignment along the cross axis (perpendicular to the main axis). In the default flex-direction: row, justify-content is horizontal and align-items is vertical.

How do I wrap flex items to the next line?

Add flex-wrap: wrap to the flex container. By default, Flexbox keeps all items on a single line and shrinks them to fit. With flex-wrap: wrap, items that exceed the container width flow onto the next line.

What is the difference between flex-basis and width?

flex-basis sets the initial size of a flex item before flex-grow and flex-shrink are applied. width sets the size regardless of flex context. When an element is a flex item, flex-basis takes priority over width (in row layouts) or height (in column layouts). See MDN: flex-basis.

Why is my flex item not shrinking?

The most common cause is the item's content enforcing a minimum size. By default, flex items will not shrink below their min-content size. Add min-width: 0 (for row layouts) or min-height: 0 (for column layouts) to the item, or use overflow: hidden to allow the item to shrink past its content size.

How does the order property work in Flexbox?

The order property controls the visual order of flex items without changing the HTML source order. All items default to order: 0. Items with lower values appear first. Items with the same value follow their source order. Note that order only changes visual rendering, not tab order or screen reader order.

Can I use Flexbox for a grid of cards?

Yes. Set the container to display: flex with flex-wrap: wrap, and give each card a flex-basis (e.g., calc(33.33% - 1rem) for three columns with gaps). Use the gap property for consistent spacing. For complex grid layouts with strict row-and-column alignment, CSS Grid may be a better fit.

References

Related Tools