Skip to content

Flex Wrap and the flex Property

By default, flex items never wrap — they squeeze onto a single line even if they overflow the container. flex-wrap changes this behavior. And the flex shorthand — covering flex-grow, flex-shrink, and flex-basis — gives items the ability to resize themselves intelligently to fill or share available space.

.tours-grid {
display: flex;
flex-wrap: wrap;
}
ValueEffect
nowrapAll items on one line, possibly overflowing (default)
wrapItems wrap to new lines when they don’t fit
wrap-reverseItems wrap to lines above instead of below

With flex-wrap: wrap, items that do not fit on the current line drop to the next line. Each “row” within a wrapping flex container behaves as its own flex line — items on a new line start fresh rather than trying to align with items from the previous line.

This is the key technique for building responsive card grids: set a minimum width on each card, enable flex-wrap, and let the browser determine how many cards fit on each row based on the viewport width.

flex-basis sets the initial size of a flex item before any growing or shrinking occurs. It replaces width (in a row layout) or height (in a column layout) as the sizing reference point:

.tour-card {
flex-basis: 300px; /* start at 300px, then grow or shrink from there */
}

flex-basis: auto (the default) tells the item to use its own width or height if set, or to size itself based on its content.

flex-grow controls whether and how much a flex item expands to fill available space. The value is a unitless ratio:

.main-content {
flex-grow: 1; /* takes all available space */
}
.sidebar {
flex-grow: 0; /* does not grow (default) */
}

With multiple growing items, the available space is distributed in proportion to their flex-grow values:

.main-content { flex-grow: 2; } /* gets twice as much space as sidebar */
.sidebar { flex-grow: 1; }

flex-grow: 0 (the default) means the item will not expand beyond its flex-basis.

flex-shrink — allowing items to compress

Section titled “flex-shrink — allowing items to compress”

flex-shrink controls whether and how much a flex item compresses when there is not enough space:

.sidebar {
flex-shrink: 0; /* never shrink — maintains its flex-basis width */
}
.main-content {
flex-shrink: 1; /* shrinks proportionally if needed (default) */
}

flex-shrink: 1 (the default) allows items to shrink proportionally. flex-shrink: 0 prevents an item from shrinking below its flex-basis.

Instead of setting flex-grow, flex-shrink, and flex-basis separately, use the flex shorthand:

/* flex: grow shrink basis */
.tour-card {
flex: 1 1 300px; /* grow: 1, shrink: 1, basis: 300px */
}

Common shorthand patterns:

flex: 1; /* flex: 1 1 0 — grow and shrink equally, start from nothing */
flex: auto; /* flex: 1 1 auto — grow and shrink, start from content size */
flex: none; /* flex: 0 0 auto — fixed size, no grow or shrink */
flex: 0 0 200px; /* fixed 200px, never grow or shrink */

flex: 1 is the most common pattern — it makes all items share available space equally.

Building a responsive card grid with flex-wrap

Section titled “Building a responsive card grid with flex-wrap”

Combine flex-wrap and flex to create a grid that adapts to the viewport:

.tours-grid {
display: flex;
flex-wrap: wrap;
gap: 2rem;
}
.tour-card {
flex: 1 1 280px; /* each card is at least 280px, but can grow to fill space */
}

With this setup:

  • On a wide viewport (1200px+), cards sit three or four to a row
  • On a medium viewport (768px), cards sit two to a row
  • On a narrow viewport (mobile), each card takes the full width

No media queries needed for the basic wrapping behavior — flex-wrap handles it automatically.

align-content — cross-axis alignment for multiple rows

Section titled “align-content — cross-axis alignment for multiple rows”

When items wrap onto multiple lines, align-content controls how those lines are distributed along the cross axis:

.tours-grid {
display: flex;
flex-wrap: wrap;
align-content: flex-start; /* lines pack at the top */
}

align-content only has an effect when there are multiple lines (i.e., when flex-wrap: wrap is set and items have actually wrapped). It behaves like justify-content but targets the stacking of wrapped rows rather than items within a row.

Build a wrapping tour card grid:

  1. Update the .tours-grid rule:
.tours-grid {
display: flex;
flex-wrap: wrap;
gap: 2rem;
padding: 2rem 0;
}
  1. Give each card a flexible but minimum size:
.tour-card {
flex: 1 1 280px;
background-color: #fff;
border: 1px solid #e0ddd8;
border-radius: 8px;
overflow: hidden;
}
  1. Open the browser and resize the window slowly from wide to narrow. Watch the cards reflow — first three to a row, then two, then one.

  2. If you want to prevent cards from becoming very wide on large monitors, add a max-width:

.tour-card {
flex: 1 1 280px;
max-width: 400px;
}
  1. In DevTools, try changing flex-wrap from wrap to nowrap and observe how cards overflow the container when wrapping is disabled.
  • flex-wrap: wrap allows items to flow onto new lines when they exceed the container’s width; nowrap (default) keeps everything on one line.
  • flex-basis sets the item’s initial size before any growing or shrinking.
  • flex-grow controls whether and how much items expand to fill available space; 0 means no growing.
  • flex-shrink controls whether and how much items compress when space is tight; 0 prevents shrinking.
  • The flex shorthand sets all three: flex: grow shrink basis. flex: 1 is shorthand for equal sharing of space.
  • Combining flex-wrap: wrap with flex: 1 1 <min-size> creates a responsive card grid without media queries.

Lesson 06 applies everything from this module to build the three key STO layout patterns: the navigation bar, the tour card row, and the centered hero section.