15 CSS Flexbox Layouts 06 / 15
CSS Flexbox Responsive Product Cards
An e-commerce product card grid using <code>flex: 1 1 180px</code> with a max-width cap — cards reflow from four columns to one with no JavaScript or media queries.
The code
<div class="fl-06">
<div class="fl-06__header">
<h2 class="fl-06__title">Product Collection</h2>
<div class="fl-06__sort">Sort: Popular ▾</div>
</div>
<p class="fl-06__subtitle">flex: 1 1 180px — naturally wraps to 4, 3, 2, or 1 column at any width</p>
<div class="fl-06__grid">
<div class="fl-06__card">
<div class="fl-06__thumb">
<div class="fl-06__thumb-bg" style="background:linear-gradient(145deg,#fff1eb,#ffd4ba)">
<svg class="fl-06__product-shape" width="70" height="70" viewBox="0 0 70 70">
<ellipse cx="35" cy="40" rx="28" ry="20" fill="#ea580c" opacity="0.15"/>
<rect x="20" y="12" width="30" height="36" rx="8" fill="#ea580c"/>
<rect x="26" y="6" width="18" height="12" rx="4" fill="#c2410c"/>
</svg>
</div>
<div class="fl-06__badge" style="background:#ef4444;color:#fff">Sale</div>
<div class="fl-06__wishlist">♡</div>
</div>
<div class="fl-06__body">
<div class="fl-06__cat">Gear</div>
<div class="fl-06__name">Thermal Flask Pro</div>
<div class="fl-06__stars">
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star" style="opacity:0.3">★</span>
<span class="fl-06__rating-count">(241)</span>
</div>
<div class="fl-06__footer">
<div class="fl-06__price">
<div class="fl-06__price-now">$24</div>
<div class="fl-06__price-was">$39</div>
</div>
<div class="fl-06__add-btn">+</div>
</div>
</div>
</div>
<div class="fl-06__card">
<div class="fl-06__thumb">
<div class="fl-06__thumb-bg" style="background:linear-gradient(145deg,#fef9ec,#fde68a)">
<svg class="fl-06__product-shape" width="70" height="70" viewBox="0 0 70 70">
<circle cx="35" cy="35" r="26" fill="#fbbf24" opacity="0.3"/>
<circle cx="35" cy="35" r="18" fill="#d97706"/>
<circle cx="35" cy="35" r="8" fill="#fef9ec"/>
</svg>
</div>
<div class="fl-06__badge" style="background:#0ea5e9;color:#fff">New</div>
<div class="fl-06__wishlist">♡</div>
</div>
<div class="fl-06__body">
<div class="fl-06__cat">Audio</div>
<div class="fl-06__name">Studio Buds X</div>
<div class="fl-06__stars">
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star">★</span>
<span class="fl-06__rating-count">(88)</span>
</div>
<div class="fl-06__footer">
<div class="fl-06__price">
<div class="fl-06__price-now">$89</div>
</div>
<div class="fl-06__add-btn">+</div>
</div>
</div>
</div>
<div class="fl-06__card">
<div class="fl-06__thumb">
<div class="fl-06__thumb-bg" style="background:linear-gradient(145deg,#f0fdf4,#bbf7d0)">
<svg class="fl-06__product-shape" width="70" height="70" viewBox="0 0 70 70">
<rect x="15" y="20" width="40" height="30" rx="6" fill="#16a34a" opacity="0.2"/>
<rect x="20" y="15" width="30" height="32" rx="6" fill="#22c55e"/>
<circle cx="35" cy="42" r="4" fill="#f0fdf4"/>
</svg>
</div>
<div class="fl-06__badge" style="background:#22c55e;color:#fff">Eco</div>
<div class="fl-06__wishlist">♡</div>
</div>
<div class="fl-06__body">
<div class="fl-06__cat">Home</div>
<div class="fl-06__name">Bamboo Notebook Set</div>
<div class="fl-06__stars">
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star" style="opacity:0.3">★</span>
<span class="fl-06__rating-count">(56)</span>
</div>
<div class="fl-06__footer">
<div class="fl-06__price">
<div class="fl-06__price-now">$18</div>
<div class="fl-06__price-was">$25</div>
</div>
<div class="fl-06__add-btn">+</div>
</div>
</div>
</div>
<div class="fl-06__card">
<div class="fl-06__thumb">
<div class="fl-06__thumb-bg" style="background:linear-gradient(145deg,#fdf4ff,#f5d0fe)">
<svg class="fl-06__product-shape" width="70" height="70" viewBox="0 0 70 70">
<rect x="18" y="18" width="34" height="34" rx="10" fill="#a855f7" opacity="0.25"/>
<rect x="22" y="22" width="26" height="26" rx="8" fill="#7c3aed"/>
<rect x="29" y="29" width="12" height="12" rx="4" fill="#f5d0fe"/>
</svg>
</div>
<div class="fl-06__wishlist">♡</div>
</div>
<div class="fl-06__body">
<div class="fl-06__cat">Tech</div>
<div class="fl-06__name">Wireless Charger Pad</div>
<div class="fl-06__stars">
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star">★</span>
<span class="fl-06__rating-count">(312)</span>
</div>
<div class="fl-06__footer">
<div class="fl-06__price">
<div class="fl-06__price-now">$42</div>
</div>
<div class="fl-06__add-btn" style="background:#7c3aed">+</div>
</div>
</div>
</div>
</div>
</div> <div class="fl-06">
<div class="fl-06__header">
<h2 class="fl-06__title">Product Collection</h2>
<div class="fl-06__sort">Sort: Popular ▾</div>
</div>
<p class="fl-06__subtitle">flex: 1 1 180px — naturally wraps to 4, 3, 2, or 1 column at any width</p>
<div class="fl-06__grid">
<div class="fl-06__card">
<div class="fl-06__thumb">
<div class="fl-06__thumb-bg" style="background:linear-gradient(145deg,#fff1eb,#ffd4ba)">
<svg class="fl-06__product-shape" width="70" height="70" viewBox="0 0 70 70">
<ellipse cx="35" cy="40" rx="28" ry="20" fill="#ea580c" opacity="0.15"/>
<rect x="20" y="12" width="30" height="36" rx="8" fill="#ea580c"/>
<rect x="26" y="6" width="18" height="12" rx="4" fill="#c2410c"/>
</svg>
</div>
<div class="fl-06__badge" style="background:#ef4444;color:#fff">Sale</div>
<div class="fl-06__wishlist">♡</div>
</div>
<div class="fl-06__body">
<div class="fl-06__cat">Gear</div>
<div class="fl-06__name">Thermal Flask Pro</div>
<div class="fl-06__stars">
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star" style="opacity:0.3">★</span>
<span class="fl-06__rating-count">(241)</span>
</div>
<div class="fl-06__footer">
<div class="fl-06__price">
<div class="fl-06__price-now">$24</div>
<div class="fl-06__price-was">$39</div>
</div>
<div class="fl-06__add-btn">+</div>
</div>
</div>
</div>
<div class="fl-06__card">
<div class="fl-06__thumb">
<div class="fl-06__thumb-bg" style="background:linear-gradient(145deg,#fef9ec,#fde68a)">
<svg class="fl-06__product-shape" width="70" height="70" viewBox="0 0 70 70">
<circle cx="35" cy="35" r="26" fill="#fbbf24" opacity="0.3"/>
<circle cx="35" cy="35" r="18" fill="#d97706"/>
<circle cx="35" cy="35" r="8" fill="#fef9ec"/>
</svg>
</div>
<div class="fl-06__badge" style="background:#0ea5e9;color:#fff">New</div>
<div class="fl-06__wishlist">♡</div>
</div>
<div class="fl-06__body">
<div class="fl-06__cat">Audio</div>
<div class="fl-06__name">Studio Buds X</div>
<div class="fl-06__stars">
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star">★</span>
<span class="fl-06__rating-count">(88)</span>
</div>
<div class="fl-06__footer">
<div class="fl-06__price">
<div class="fl-06__price-now">$89</div>
</div>
<div class="fl-06__add-btn">+</div>
</div>
</div>
</div>
<div class="fl-06__card">
<div class="fl-06__thumb">
<div class="fl-06__thumb-bg" style="background:linear-gradient(145deg,#f0fdf4,#bbf7d0)">
<svg class="fl-06__product-shape" width="70" height="70" viewBox="0 0 70 70">
<rect x="15" y="20" width="40" height="30" rx="6" fill="#16a34a" opacity="0.2"/>
<rect x="20" y="15" width="30" height="32" rx="6" fill="#22c55e"/>
<circle cx="35" cy="42" r="4" fill="#f0fdf4"/>
</svg>
</div>
<div class="fl-06__badge" style="background:#22c55e;color:#fff">Eco</div>
<div class="fl-06__wishlist">♡</div>
</div>
<div class="fl-06__body">
<div class="fl-06__cat">Home</div>
<div class="fl-06__name">Bamboo Notebook Set</div>
<div class="fl-06__stars">
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star" style="opacity:0.3">★</span>
<span class="fl-06__rating-count">(56)</span>
</div>
<div class="fl-06__footer">
<div class="fl-06__price">
<div class="fl-06__price-now">$18</div>
<div class="fl-06__price-was">$25</div>
</div>
<div class="fl-06__add-btn">+</div>
</div>
</div>
</div>
<div class="fl-06__card">
<div class="fl-06__thumb">
<div class="fl-06__thumb-bg" style="background:linear-gradient(145deg,#fdf4ff,#f5d0fe)">
<svg class="fl-06__product-shape" width="70" height="70" viewBox="0 0 70 70">
<rect x="18" y="18" width="34" height="34" rx="10" fill="#a855f7" opacity="0.25"/>
<rect x="22" y="22" width="26" height="26" rx="8" fill="#7c3aed"/>
<rect x="29" y="29" width="12" height="12" rx="4" fill="#f5d0fe"/>
</svg>
</div>
<div class="fl-06__wishlist">♡</div>
</div>
<div class="fl-06__body">
<div class="fl-06__cat">Tech</div>
<div class="fl-06__name">Wireless Charger Pad</div>
<div class="fl-06__stars">
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star">★</span><span class="fl-06__star">★</span>
<span class="fl-06__star">★</span>
<span class="fl-06__rating-count">(312)</span>
</div>
<div class="fl-06__footer">
<div class="fl-06__price">
<div class="fl-06__price-now">$42</div>
</div>
<div class="fl-06__add-btn" style="background:#7c3aed">+</div>
</div>
</div>
</div>
</div>
</div>.fl-06, .fl-06 *, .fl-06 *::before, .fl-06 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.fl-06 ::selection { background: #fb923c; color: #fff; }
.fl-06 {
--bg: #fff8f4;
--surface: #fff;
--ink: #1a0a00;
--muted: #9a7a65;
--accent: #ea580c;
--accent2: #fb923c;
--border: rgba(234,88,12,0.12);
--star: #fbbf24;
font-family: 'Outfit', sans-serif;
background: var(--bg);
padding: 24px;
border-radius: 16px;
min-height: 500px;
}
.fl-06__header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
}
.fl-06__title {
font-size: 1.2rem;
font-weight: 800;
color: var(--ink);
}
.fl-06__sort {
display: flex;
align-items: center;
gap: 6px;
font-size: 0.75rem;
font-weight: 600;
color: var(--muted);
cursor: pointer;
}
.fl-06__subtitle {
font-size: 0.78rem;
color: var(--muted);
margin-bottom: 18px;
}
/* Product grid: flex-wrap + flex-basis for fluid columns */
.fl-06__grid {
display: flex;
flex-wrap: wrap;
gap: 14px;
}
.fl-06__card {
flex: 1 1 180px; /* grow, shrink, min-basis = fluid cols */
max-width: calc(25% - 11px); /* max 4 per row */
background: var(--surface);
border: 1px solid var(--border);
border-radius: 14px;
overflow: hidden;
display: flex;
flex-direction: column;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.fl-06__card:hover {
transform: translateY(-4px);
box-shadow: 0 14px 40px rgba(234,88,12,0.12);
}
.fl-06__thumb {
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
}
.fl-06__thumb-bg {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.fl-06__product-shape {
transition: transform 0.3s;
}
.fl-06__card:hover .fl-06__product-shape {
transform: scale(1.08) rotate(3deg);
}
.fl-06__badge {
position: absolute;
top: 10px;
left: 10px;
font-size: 0.62rem;
font-weight: 800;
padding: 3px 8px;
border-radius: 4px;
text-transform: uppercase;
letter-spacing: 0.06em;
}
.fl-06__wishlist {
position: absolute;
top: 10px;
right: 10px;
width: 28px;
height: 28px;
background: rgba(255,255,255,0.9);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.8rem;
cursor: pointer;
}
.fl-06__body {
padding: 12px;
display: flex;
flex-direction: column;
gap: 4px;
flex: 1;
}
.fl-06__cat {
font-size: 0.65rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--muted);
}
.fl-06__name {
font-size: 0.88rem;
font-weight: 700;
color: var(--ink);
line-height: 1.3;
}
.fl-06__stars {
display: flex;
align-items: center;
gap: 2px;
font-size: 0.7rem;
}
.fl-06__star { color: var(--star); }
.fl-06__rating-count {
font-size: 0.65rem;
color: var(--muted);
margin-left: 4px;
}
.fl-06__footer {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: auto;
padding-top: 10px;
border-top: 1px solid var(--border);
}
.fl-06__price {
display: flex;
align-items: baseline;
gap: 5px;
}
.fl-06__price-now {
font-size: 1rem;
font-weight: 800;
color: var(--accent);
}
.fl-06__price-was {
font-size: 0.75rem;
text-decoration: line-through;
color: var(--muted);
}
.fl-06__add-btn {
width: 30px;
height: 30px;
border-radius: 8px;
background: var(--accent);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 1rem;
font-weight: 700;
cursor: pointer;
transition: background 0.2s, transform 0.15s;
flex-shrink: 0;
}
.fl-06__add-btn:hover { background: #c2410c; transform: scale(1.1); }
@media (prefers-reduced-motion: reduce) {
.fl-06__card, .fl-06__product-shape, .fl-06__add-btn { transition: none; }
} .fl-06, .fl-06 *, .fl-06 *::before, .fl-06 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.fl-06 ::selection { background: #fb923c; color: #fff; }
.fl-06 {
--bg: #fff8f4;
--surface: #fff;
--ink: #1a0a00;
--muted: #9a7a65;
--accent: #ea580c;
--accent2: #fb923c;
--border: rgba(234,88,12,0.12);
--star: #fbbf24;
font-family: 'Outfit', sans-serif;
background: var(--bg);
padding: 24px;
border-radius: 16px;
min-height: 500px;
}
.fl-06__header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
}
.fl-06__title {
font-size: 1.2rem;
font-weight: 800;
color: var(--ink);
}
.fl-06__sort {
display: flex;
align-items: center;
gap: 6px;
font-size: 0.75rem;
font-weight: 600;
color: var(--muted);
cursor: pointer;
}
.fl-06__subtitle {
font-size: 0.78rem;
color: var(--muted);
margin-bottom: 18px;
}
/* Product grid: flex-wrap + flex-basis for fluid columns */
.fl-06__grid {
display: flex;
flex-wrap: wrap;
gap: 14px;
}
.fl-06__card {
flex: 1 1 180px; /* grow, shrink, min-basis = fluid cols */
max-width: calc(25% - 11px); /* max 4 per row */
background: var(--surface);
border: 1px solid var(--border);
border-radius: 14px;
overflow: hidden;
display: flex;
flex-direction: column;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.fl-06__card:hover {
transform: translateY(-4px);
box-shadow: 0 14px 40px rgba(234,88,12,0.12);
}
.fl-06__thumb {
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
}
.fl-06__thumb-bg {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.fl-06__product-shape {
transition: transform 0.3s;
}
.fl-06__card:hover .fl-06__product-shape {
transform: scale(1.08) rotate(3deg);
}
.fl-06__badge {
position: absolute;
top: 10px;
left: 10px;
font-size: 0.62rem;
font-weight: 800;
padding: 3px 8px;
border-radius: 4px;
text-transform: uppercase;
letter-spacing: 0.06em;
}
.fl-06__wishlist {
position: absolute;
top: 10px;
right: 10px;
width: 28px;
height: 28px;
background: rgba(255,255,255,0.9);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.8rem;
cursor: pointer;
}
.fl-06__body {
padding: 12px;
display: flex;
flex-direction: column;
gap: 4px;
flex: 1;
}
.fl-06__cat {
font-size: 0.65rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--muted);
}
.fl-06__name {
font-size: 0.88rem;
font-weight: 700;
color: var(--ink);
line-height: 1.3;
}
.fl-06__stars {
display: flex;
align-items: center;
gap: 2px;
font-size: 0.7rem;
}
.fl-06__star { color: var(--star); }
.fl-06__rating-count {
font-size: 0.65rem;
color: var(--muted);
margin-left: 4px;
}
.fl-06__footer {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: auto;
padding-top: 10px;
border-top: 1px solid var(--border);
}
.fl-06__price {
display: flex;
align-items: baseline;
gap: 5px;
}
.fl-06__price-now {
font-size: 1rem;
font-weight: 800;
color: var(--accent);
}
.fl-06__price-was {
font-size: 0.75rem;
text-decoration: line-through;
color: var(--muted);
}
.fl-06__add-btn {
width: 30px;
height: 30px;
border-radius: 8px;
background: var(--accent);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 1rem;
font-weight: 700;
cursor: pointer;
transition: background 0.2s, transform 0.15s;
flex-shrink: 0;
}
.fl-06__add-btn:hover { background: #c2410c; transform: scale(1.1); }
@media (prefers-reduced-motion: reduce) {
.fl-06__card, .fl-06__product-shape, .fl-06__add-btn { transition: none; }
}How this works
Each card uses flex: 1 1 180px meaning it can grow to fill space, shrink below 180px if needed, and starts at 180px. A max-width: calc(25% - 11px) prevents cards from growing beyond a quarter of the row on wide containers. As the container narrows, cards wrap into 3, 2, then 1 column naturally.
Card internals use a column flex with the image as a fixed block, product info section with flex: 1 to push the buy button to the bottom, and an align-self: flex-end button row. Badge overlays use position: absolute within position: relative card containers — the only non-flex positioning in the demo.
Customize
- Change the minimum card width by editing the
flex-basis(the third flex shorthand value) from180pxto your target breakpoint. - Remove the max-width cap by deleting
max-widthon cards — they then stretch to fill entire rows when few items exist. - Add a skeleton loading state by replacing card content with
background: linear-gradientanimated shimmer blocks using the same card shell. - Implement a list-view toggle by switching the card container from
flex-wrap: wraptoflex-direction: columnvia a class toggle. - Adjust the grid gap uniformly by editing the
gapon.fl-06__grid; card basis auto-reflows around the new spacing.
Watch out for
- The
max-widthcalculation must account forgap— usecalc(25% - (gap * 3/4))for exact four-column capping, otherwise cards can overflow. flex: 1 1 180pxallows shrinking below 180px if the container is very narrow — setmin-width: 160pxif a hard minimum is needed.- Percentage max-width on flex children is calculated against the flex container width, not the viewport — make sure the container is full-width or adjust percentages accordingly.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 84+ | 14.1+ | 63+ | 84+ |
The gap shorthand on flex requires Chrome 84+, Safari 14.1+; fall back to margin with a negative container offset for older browsers.