Skip to main content

What is Flexbox?

Flexbox is a one-dimensional layout model - it handles layout in either a row or column. Ideal for:
  • Navigation bars
  • Centering content
  • Equal-height columns
  • Space distribution
  • Simple component layouts

Flexbox Terminology

Main Axis (horizontal by default)
┌─────────────────────────────────────┐
│                                       │
│  [─Item 1─] [─Item 2─] [─Item 3─]  │ Cross Axis
│                                       │ (vertical)
└─────────────────────────────────────┘
  • Flex Container - Parent element with display: flex
  • Flex Items - Direct children of the container
  • Main Axis - Primary direction (row = horizontal, column = vertical)
  • Cross Axis - Perpendicular to main axis

Creating a Flex Container

.container {
  display: flex;
}
That’s it! Child elements are now flex items.

Container Properties

flex-direction

Sets the main axis direction.
.container {
  flex-direction: row;
  /* Items flow left to right → */
}

justify-content

Aligns items along the main axis.
.container {
  justify-content: flex-start;
  /* [■■■]_____________ */
}

align-items

Aligns items along the cross axis.
.container {
  align-items: stretch;
  /* Items stretch to fill height */
}

gap

Space between flex items (modern property!).
.container {
  display: flex;
  gap: 16px;              /* Equal gap all around */
  gap: 16px 32px;         /* row-gap column-gap */
  row-gap: 16px;          /* Vertical gap */
  column-gap: 32px;       /* Horizontal gap */
}
gap is much cleaner than using margins on items!

flex-wrap

Controls wrapping to multiple lines.
.container {
  flex-wrap: nowrap;
  /* Items stay on one line, may shrink */
}

Item Properties

flex-grow

How much an item should grow relative to others.
.item {
  flex-grow: 1;
  /* All items grow equally */
}

flex-shrink

How much an item should shrink when space is tight.
.item {
  flex-shrink: 1;  /* Can shrink (default) */
  flex-shrink: 0;  /* Won't shrink */
}

flex-basis

Initial size before growing/shrinking.
.item {
  flex-basis: 200px;   /* Start at 200px */
  flex-basis: auto;    /* Use content size (default) */
  flex-basis: 0;       /* Start at 0, only use flex-grow */
}

flex (Shorthand)

flex: grow shrink basis;
.item {
  flex: 1;           /* flex-grow: 1, shrink: 1, basis: 0 */
  flex: 0;           /* Don't grow or shrink */
  flex: auto;        /* grow: 1, shrink: 1, basis: auto */
  flex: none;        /* grow: 0, shrink: 0, basis: auto */
}

align-self

Override align-items for a specific item.
.container {
  align-items: flex-start;  /* All items at top */
}

.special-item {
  align-self: flex-end;     /* This one at bottom */
}

Real Examples from the Project

Header Container

.header__container {
  display: flex;
  align-items: center;           /* Vertical center */
  justify-content: space-between; /* Logo left, nav right */
  gap: var(--spacing-md);         /* 16px between items */
  max-width: var(--container-max-width);
  margin: 0 auto;
  padding: var(--spacing-md) var(--spacing-lg);
}
.header__logo-link {
  display: flex;
  align-items: baseline;  /* Align by text baseline */
  gap: var(--spacing-xs); /* 4px between logo parts */
}
.header__search {
  flex: 1;              /* Take available space */
  max-width: 600px;     /* But not too wide */
}

.header__search-form {
  display: flex;
  border-radius: var(--border-radius-sm);
  overflow: hidden;
}

.header__search-input {
  flex: 1;              /* Input takes available space */
  padding: var(--spacing-sm) var(--spacing-md);
  min-width: 0;         /* Allow shrinking below content size */
}
Use min-width: 0 on flex items that should shrink - by default they won’t shrink below content size.
.header__nav-list {
  display: flex;
  align-items: center;
  gap: var(--spacing-md);
}

.header__nav-link {
  display: flex;
  align-items: center;
  gap: var(--spacing-xs);
  white-space: nowrap;  /* Don't break text */
}

Search Button

.header__search-button {
  display: flex;
  align-items: center;
  justify-content: center;  /* Center icon/text */
  padding: var(--spacing-sm) var(--spacing-md);
}

Categories (Horizontal Scroll)

.header__categories-list {
  display: flex;
  gap: var(--spacing-lg);
  overflow-x: auto;              /* Scroll on overflow */
  -webkit-overflow-scrolling: touch; /* Smooth iOS scroll */
  
  /* Hide scrollbar */
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.header__categories-list::-webkit-scrollbar {
  display: none;
}

Products Header

.products__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;        /* Wrap on small screens */
  gap: var(--spacing-md);
}

Loading State

.products__loading {
  display: flex;
  flex-direction: column;  /* Stack vertically */
  align-items: center;
  gap: var(--spacing-md);
  padding: var(--spacing-2xl);
}
.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--spacing-md);
}
.footer__links {
  display: flex;
  flex-direction: column;  /* Stack links vertically */
  gap: var(--spacing-sm);
}

Common Patterns

Perfect Centering

.container {
  display: flex;
  justify-content: center;  /* Horizontal center */
  align-items: center;      /* Vertical center */
  min-height: 100vh;        /* Full viewport height */
}

Holy Grail Layout

.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.header { /* Fixed height */ }

.main {
  flex: 1;  /* Takes remaining space */
}

.footer { /* Fixed height */ }

Equal Width Columns

.row {
  display: flex;
  gap: 20px;
}

.column {
  flex: 1;  /* All columns equal width */
}

Fixed Sidebar + Flexible Content

.layout {
  display: flex;
}

.sidebar {
  flex: 0 0 250px;  /* Don't grow/shrink, fixed 250px */
}

.content {
  flex: 1;  /* Takes remaining space */
}

Space Between Elements

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

/* First item left, last item right */

Button Group

.button-group {
  display: flex;
  gap: 8px;
}

.button {
  flex: 1;  /* Buttons share space equally */
}

Responsive Flexbox

Wrap on Small Screens

.header__container {
  display: flex;
  flex-wrap: wrap;
}

@media (max-width: 768px) {
  .header__search {
    order: 3;           /* Move to end */
    flex-basis: 100%;   /* Take full width */
  }
}

Column on Mobile

.row {
  display: flex;
  gap: 20px;
}

@media (max-width: 768px) {
  .row {
    flex-direction: column;  /* Stack vertically */
  }
}

Flexbox vs Grid

Use CaseFlexboxGrid
Navigation✅ Perfect❌ Overkill
Centering✅ Great✅ Also great
Card layouts❌ Limited✅ Perfect
2D layouts❌ Hard✅ Easy
Unknown items✅ Flexible❌ Needs structure
Flexbox = One dimension (row or column) Grid = Two dimensions (rows and columns)

Common Pitfalls

Items Overflowing

.item {
  flex: 1;
  /* May overflow if content is too wide */
}

Text Not Wrapping

.item {
  white-space: nowrap;  /* Forces single line */
  overflow: hidden;
  text-overflow: ellipsis;  /* Shows ... */
}

Quick Reference

Container Properties

  • display: flex - Create flex container
  • flex-direction - row | column
  • justify-content - Main axis alignment
  • align-items - Cross axis alignment
  • gap - Space between items
  • flex-wrap - Wrap to multiple lines

Item Properties

  • flex-grow - Growth factor
  • flex-shrink - Shrink factor
  • flex-basis - Initial size
  • flex - Shorthand
  • align-self - Override alignment
  • order - Visual order

Next Steps

Grid

Learn two-dimensional layouts

Responsive Design

Make flexbox responsive

Build docs developers (and LLMs) love