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.
flex-wrap
Section titled “flex-wrap”.tours-grid { display: flex; flex-wrap: wrap;}| Value | Effect |
|---|---|
nowrap | All items on one line, possibly overflowing (default) |
wrap | Items wrap to new lines when they don’t fit |
wrap-reverse | Items 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 — the item’s starting size
Section titled “flex-basis — the item’s starting size”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 — allowing items to expand
Section titled “flex-grow — allowing items to expand”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.
The flex shorthand
Section titled “The flex shorthand”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.
Exercise
Section titled “Exercise”Build a wrapping tour card grid:
- Update the
.tours-gridrule:
.tours-grid { display: flex; flex-wrap: wrap; gap: 2rem; padding: 2rem 0;}- 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;}-
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.
-
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;}- In DevTools, try changing
flex-wrapfromwraptonowrapand observe how cards overflow the container when wrapping is disabled.
flex-wrap: wrapallows items to flow onto new lines when they exceed the container’s width;nowrap(default) keeps everything on one line.flex-basissets the item’s initial size before any growing or shrinking.flex-growcontrols whether and how much items expand to fill available space;0means no growing.flex-shrinkcontrols whether and how much items compress when space is tight;0prevents shrinking.- The
flexshorthand sets all three:flex: grow shrink basis.flex: 1is shorthand for equal sharing of space. - Combining
flex-wrap: wrapwithflex: 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.