# The Flexbox Tutorial

> Learn CSS Flexbox using the main and cross axes, then control direction, alignment, wrapping, gaps, ordering, and how individual items grow or shrink.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2018-02-05 | Updated: 2026-07-18 | Topics: [CSS](https://flaviocopes.com/tags/css/) | Canonical: https://flaviocopes.com/flexbox/

<!-- TOC -->

- [What is Flexbox?](#what-is-flexbox)
- [Enable Flexbox](#enable-flexbox)
- [Understand the two axes](#understand-the-two-axes)
- [Container properties](#container-properties)
  - [Choose a direction](#choose-a-direction)
  - [Align items on the main axis](#align-items-on-the-main-axis)
  - [Align items on the cross axis](#align-items-on-the-cross-axis)
  - [Wrap items onto multiple lines](#wrap-items-onto-multiple-lines)
  - [Add gaps](#add-gaps)
- [Flex item properties](#flex-item-properties)
  - [Change visual order](#change-visual-order)
  - [Override cross-axis alignment](#override-cross-axis-alignment)
  - [Grow and shrink items](#grow-and-shrink-items)
  - [Use the flex shorthand](#use-the-flex-shorthand)

<!-- /TOC -->

## What is Flexbox?

Flexbox is a one-dimensional CSS layout model.

It lays out items along one main axis: a row or a column. CSS Grid is usually a better fit when you need to control rows and columns together.

Flexbox is useful for navigation bars, groups of controls, card rows, centering, and other layouts where items share one direction.

Try the properties in my [flexbox playground](https://flaviocopes.com/tools/flexbox-playground/) as you read.

The [CSS Flexible Box Layout specification](https://www.w3.org/TR/css-flexbox-1/) defines the layout model.

## Enable Flexbox

Set `display: flex` on the parent:

```css
.container {
  display: flex;
}
```

Its direct children become flex items.

Use `inline-flex` when the flex container itself should behave like an inline-level element:

```css
.container {
  display: inline-flex;
}
```

## Understand the two axes

Flexbox uses a **main axis** and a **cross axis**.

`flex-direction` chooses the main axis. The cross axis runs perpendicular to it.

This terminology matters because the axes are not always horizontal and vertical. They also depend on the document's writing mode and text direction.

- `justify-content` aligns items on the main axis
- `align-items` aligns items on the cross axis

## Container properties

Container properties define how all its flex items participate in the layout.

The main ones are:

- `flex-direction`
- `justify-content`
- `align-items`
- `align-content`
- `flex-wrap`
- `flex-flow`
- `gap`

### Choose a direction

`flex-direction` sets the main axis:

- `row` follows the inline text direction
- `row-reverse` follows it in reverse
- `column` follows the block direction
- `column-reverse` follows it in reverse

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

`row` is the default.

![Rows or columns](https://flaviocopes.com/images/flexbox/1.png)

### Align items on the main axis

`justify-content` distributes free space along the main axis.

Common values are:

- `flex-start`
- `flex-end`
- `center`
- `space-between`
- `space-around`
- `space-evenly`

```css
.container {
  display: flex;
  justify-content: space-between;
}
```

If `flex-direction` is `row`, this usually changes horizontal distribution. If it is `column`, it usually changes vertical distribution.

![Main-axis alignment](https://flaviocopes.com/images/flexbox/3.png)

### Align items on the cross axis

`align-items` sets the default alignment for items within a flex line.

Common values are:

- `stretch`
- `flex-start`
- `flex-end`
- `center`
- `baseline`

```css
.container {
  display: flex;
  align-items: center;
}
```

`stretch` is the default. It only stretches an item when its cross size is `auto`.

![Cross-axis alignment](https://flaviocopes.com/images/flexbox/4.png)

`baseline` aligns items using their text baselines. This becomes easier to see when items use different font sizes.

For a wrapped container, `align-content` distributes the flex lines on the cross axis. It has no effect when there is only one line.

```css
.container {
  display: flex;
  flex-wrap: wrap;
  align-content: space-between;
}
```

### Wrap items onto multiple lines

Flex items stay on one line by default:

```css
.container {
  flex-wrap: nowrap;
}
```

Allow them to create more lines with `wrap`:

```css
.container {
  display: flex;
  flex-wrap: wrap;
}
```

`wrap-reverse` reverses the cross-start and cross-end directions. It does not reverse the order of items within each line.

The `flex-flow` shorthand combines direction and wrapping:

```css
.container {
  display: flex;
  flex-flow: row wrap;
}
```

### Add gaps

Use `gap` to add consistent space between flex items:

```css
.container {
  display: flex;
  gap: 1rem;
}
```

You can set row and column gaps separately:

```css
.container {
  row-gap: 1rem;
  column-gap: 2rem;
}
```

## Flex item properties

These properties apply to individual flex items:

- `order`
- `align-self`
- `flex-grow`
- `flex-shrink`
- `flex-basis`
- `flex`

### Change visual order

Every item starts with `order: 0`. Lower values appear first:

```css
.featured {
  order: -1;
}
```

Be careful with `order`. It changes the visual order, not the source or keyboard navigation order.

Keep the HTML order logical and accessible. Use `order` for small visual adjustments, not to repair incorrect markup.

![Moving items before or after another one](https://flaviocopes.com/images/flexbox/5.png)

### Override cross-axis alignment

An item can override the container's `align-items` value with `align-self`:

```css
.featured {
  align-self: flex-end;
}
```

It accepts the same common alignment values as `align-items`, plus `auto`.

![Per-item cross-axis alignment](https://flaviocopes.com/images/flexbox/6.png)

### Grow and shrink items

`flex-basis` sets an item's initial main size before free space is distributed:

```css
.item {
  flex-basis: 12rem;
}
```

`auto` uses the item's main-size property when provided, or its content size otherwise.

`flex-grow` controls how positive free space is shared. The default is `0`:

```css
.item {
  flex-grow: 1;
}
```

An item with `flex-grow: 2` receives twice the share of free space given to an item with `flex-grow: 1`. This does not mean its final width is always twice as large.

`flex-shrink` controls how items shrink when there is not enough space. The default is `1`:

```css
.fixed {
  flex-shrink: 0;
}
```

The browser considers both `flex-shrink` and the item's flex base size. A shrink factor of `2` does not mean the final item becomes half the size.

Long content can still prevent an item from shrinking because flex items have an automatic minimum size. Set `min-width: 0` when a row item needs to shrink below its content's minimum width:

```css
.item {
  min-width: 0;
}
```

### Use the flex shorthand

The `flex` shorthand combines:

- `flex-grow`
- `flex-shrink`
- `flex-basis`

The initial value is:

```css
.item {
  flex: 0 1 auto;
}
```

A common equal-width layout uses:

```css
.item {
  flex: 1;
}
```

Use the shorthand when you set flexibility. It resets all three parts together and makes the intended behavior clearer.

See the [MDN Flexbox guide](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexible_box_layout/Basic_concepts_of_flexbox) for more examples and browser-focused details.
