On this page

Flexbox from scratch

15 min read TextCh. 3 — Modern Layout

What is Flexbox?

Flexbox (Flexible Box Layout) is a CSS layout system designed to distribute space and align elements within a container, even when their size is unknown or dynamic.

It is activated with display: flex on the parent element. All its direct children automatically become flex items.

The two axes of Flexbox

Flexbox works on two axes:

  • Main axis: defined by flex-direction. By default, it is horizontal (left to right).
  • Cross axis: perpendicular to the main axis. By default, it is vertical.

Understanding these axes is fundamental because justify-content aligns along the main axis and align-items along the cross axis.

Flex container properties

flex-direction

Controls the direction of the main axis:

Value Direction
row Left to right (default)
row-reverse Right to left
column Top to bottom
column-reverse Bottom to top

justify-content (main axis)

Distributes items along the main axis:

Value Effect
flex-start Aligned to the start (default)
flex-end Aligned to the end
center Centered
space-between Equal space between items
space-around Equal space around each item
space-evenly Perfectly equal space between all

align-items (cross axis)

Aligns items on the cross axis:

Value Effect
stretch Stretch to fill the container (default)
flex-start Aligned to the start of the cross axis
flex-end Aligned to the end
center Vertically centered
baseline Aligned by the text baseline

flex-wrap

By default, flex items are squeezed into a single line. With flex-wrap: wrap, they can jump to the next line when there is not enough space.

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

gap

Defines the space between flex items without using margin. Accepts one or two values (row and column):

.container {
  gap: 1rem;        /* Same space on both axes */
  gap: 1rem 2rem;   /* 1rem vertical, 2rem horizontal */
}

Flex item properties

flex-grow, flex-shrink, and flex-basis

These three properties control how items expand or shrink:

  • flex-grow: how much the item grows to fill leftover space (default: 0)
  • flex-shrink: how much the item shrinks if there is not enough space (default: 1)
  • flex-basis: base size before distributing space (default: auto)

The flex shorthand

The flex property combines all three:

.item { flex: 1; }           /* grow:1, shrink:1, basis:0 */
.item { flex: 0 0 200px; }   /* Fixed size of 200px */
.item { flex: 2 1 auto; }    /* Grows twice as much, shrinks, auto basis */

align-self

Allows an individual item to align differently from the rest on the cross axis:

.special-item {
  align-self: flex-end; /* Only this item goes to the bottom */
}

order

Changes the visual order of an item without modifying the HTML:

.first { order: -1; } /* Appears before the others */
.last  { order: 99; } /* Appears at the end */

Common Flexbox patterns

Perfect centering

.centered {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
main { flex: 1; }

Responsive cards without media queries

.cards {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}
.card {
  flex: 1 1 300px; /* Minimum 300px, grows if there is space */
}

Flexbox dominates one-dimensional layouts. In the next lesson, we will learn CSS Grid, which takes two-dimensional layouts to another level.

Practice

  1. Build a navbar with Flexbox: Create a navigation bar with a logo on the left and links on the right using display: flex, justify-content: space-between, and align-items: center.
  2. Center an element vertically and horizontally: Use a flex container with justify-content: center and align-items: center to center a box in the full viewport.
  3. Create responsive cards with flex-wrap: Build a card grid using flex-wrap: wrap and flex: 1 1 300px so the cards adapt automatically without media queries.
Flexbox in one sentence
Flexbox is for one-dimensional layouts: a row OR a column. If you need to control rows AND columns at the same time, use CSS Grid.
The gap property
Use gap instead of margin to space flex items. gap only adds space BETWEEN elements, never at the start or end, which avoids the classic leftover margin problems.
/* Basic flex container */
.container {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
}

/* Classic Navbar with Flexbox */
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 2rem;
}

.navbar__links {
  display: flex;
  gap: 1.5rem;
  list-style: none;
}

/* Cards that wrap */
.grid-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
}

.grid-cards > .card {
  flex: 1 1 280px;
  padding: 1.5rem;
  border: 1px solid #ddd;
  border-radius: 8px;
}
/* Layout with sidebar + content */
.layout {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  flex: 0 0 250px; /* Does not grow, does not shrink, fixed 250px */
  background: #f5f5f5;
  padding: 1rem;
}

.content {
  flex: 1; /* Takes up all remaining space */
  padding: 2rem;
}

/* Footer stuck to the bottom */
.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.page > main {
  flex: 1; /* Pushes the footer down */
}

.page > footer {
  padding: 1rem;
  background: #1a1a2e;
  color: white;
}