This is the fastest way to create a clean, responsive product grid. We will use CSS Flexbox’s flex-wrap property.
Your CodePen isn't just for looking pretty; it needs to be functional.
Here is why this code works so well across devices:
1. The Mobile-First Approach
In the CSS, we didn't start by writing code for a desktop. We wrote the default styles for a mobile phone (single column, flex-direction: column). This ensures that the card loads quickly and looks correct on the most common devices.
2. The Media Query Pivot
Look at the @media (min-width: 600px) block. This is the plot twist in our story. Once the screen is wider than 600 pixels, we switch the flex-direction to row. The image snaps to the left, and the text snaps to the right. The image gets a width of 45%, and the text gets 55%. This is the "Responsive" magic.
3. Object-Fit: Cover
Images are notoriously difficult in responsive design. They often stretch or squish. We used object-fit: cover; on the image. This tells the browser: *"Make the image fill this
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>Responsive Product Cards | Pure CSS Grid | CodePen Ready</title>
<!-- Google Fonts + simple reset -->
<style>
*
margin: 0;
padding: 0;
box-sizing: border-box;
body
background: linear-gradient(145deg, #f4f7fc 0%, #e9eef3 100%);
font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, sans-serif;
padding: 2rem 1.5rem;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* main container */
.shop-container
max-width: 1400px;
width: 100%;
margin: 0 auto;
/* header / intro */
.gallery-header
text-align: center;
margin-bottom: 2.8rem;
.gallery-header h1
font-size: 2.3rem;
font-weight: 700;
background: linear-gradient(135deg, #1a2a3a, #2c4c6c);
background-clip: text;
-webkit-background-clip: text;
color: transparent;
letter-spacing: -0.3px;
.gallery-header p
color: #4a627a;
margin-top: 0.6rem;
font-size: 1.05rem;
font-weight: 500;
border-bottom: 2px solid rgba(44, 76, 108, 0.2);
display: inline-block;
padding-bottom: 0.4rem;
/* ---------- RESPONSIVE CARD GRID (CSS Grid) ---------- */
.card-grid
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 2rem;
justify-items: center;
align-items: stretch;
/* PRODUCT CARD - modern, smooth, interactive */
.product-card
background: #ffffff;
border-radius: 1.75rem;
overflow: hidden;
width: 100%;
max-width: 360px;
transition: transform 0.25s ease, box-shadow 0.35s ease;
box-shadow: 0 12px 28px -8px rgba(0, 0, 0, 0.08), 0 4px 12px rgba(0, 0, 0, 0.02);
display: flex;
flex-direction: column;
position: relative;
backdrop-filter: blur(0px);
.product-card:hover
transform: translateY(-6px);
box-shadow: 0 24px 36px -12px rgba(0, 0, 0, 0.2), 0 6px 18px rgba(0, 0, 0, 0.05);
/* image container - maintains ratio and responsiveness */
.card-img
background-color: #f2f5f9;
position: relative;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
padding: 1.8rem 1.2rem 1rem 1.2rem;
border-bottom: 1px solid #edf2f7;
transition: background 0.2s;
.card-img img
max-width: 85%;
height: auto;
display: block;
object-fit: contain;
transition: transform 0.4s cubic-bezier(0.2, 0.9, 0.4, 1.1);
.product-card:hover .card-img img
transform: scale(1.02);
/* badge / sale tag */
.badge
position: absolute;
top: 1rem;
left: 1rem;
background: #e11d48;
color: white;
font-size: 0.7rem;
font-weight: 700;
padding: 0.25rem 0.8rem;
border-radius: 40px;
letter-spacing: 0.3px;
backdrop-filter: blur(2px);
background-color: #e11d48;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
z-index: 2;
.badge.green
background: #0f7b3a;
/* card content */
.card-content
padding: 1.4rem 1.3rem 1.6rem;
flex: 1;
display: flex;
flex-direction: column;
.product-category
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 600;
color: #5e7a93;
margin-bottom: 0.5rem;
.product-title
font-size: 1.35rem;
font-weight: 700;
line-height: 1.3;
color: #1a2c3e;
margin-bottom: 0.5rem;
.product-description
font-size: 0.85rem;
color: #4b5e77;
line-height: 1.45;
margin-bottom: 1.2rem;
flex: 1;
/* price area + rating */
.price-rating
display: flex;
justify-content: space-between;
align-items: baseline;
flex-wrap: wrap;
margin-bottom: 1.1rem;
.price
font-size: 1.6rem;
font-weight: 800;
color: #1e4a6e;
letter-spacing: -0.5px;
.price small
font-size: 0.8rem;
font-weight: 500;
color: #5e7a93;
.old-price
font-size: 0.85rem;
color: #94a3b8;
text-decoration: line-through;
margin-left: 0.5rem;
font-weight: 500;
.rating
display: flex;
align-items: center;
gap: 0.3rem;
background: #f8fafc;
padding: 0.2rem 0.6rem;
border-radius: 40px;
.stars
color: #f5b042;
font-size: 0.75rem;
letter-spacing: 1px;
.rating-value
font-size: 0.7rem;
font-weight: 600;
color: #334155;
/* button */
.btn-card
background: #1e3a5f;
border: none;
width: 100%;
padding: 0.8rem 0;
border-radius: 2.5rem;
font-weight: 600;
font-size: 0.9rem;
color: white;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
margin-top: 0.5rem;
font-family: inherit;
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
.btn-card:hover
background: #0f2c48;
transform: scale(0.98);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
.btn-card:active
transform: scale(0.96);
/* responsive behavior for very small devices */
@media (max-width: 640px)
body
padding: 1.2rem;
.card-grid
gap: 1.3rem;
.product-title
font-size: 1.2rem;
.price
font-size: 1.4rem;
.gallery-header h1
font-size: 1.8rem;
/* optional micro-interaction for button feedback (just demo) */
.btn-card i
font-style: normal;
font-size: 1.1rem;
/* footer note */
.demo-note
text-align: center;
margin-top: 3rem;
font-size: 0.75rem;
color: #6c86a0;
border-top: 1px solid rgba(0,0,0,0.05);
padding-top: 1.5rem;
max-width: 500px;
margin-left: auto;
margin-right: auto;
</style>
</head>
<body>
<div class="shop-container">
<div class="gallery-header">
<h1>✨ responsive product cards</h1>
<p>pure HTML / CSS — fluid grid · hover effects · modern design</p>
</div>
<div class="card-grid">
<!-- CARD 1 - classic sneaker -->
<div class="product-card">
<div class="card-img">
<img src="https://cdn-icons-png.flaticon.com/512/2589/2589173.png" alt="modern sneaker" loading="lazy">
<div class="badge">🔥 bestseller</div>
</div>
<div class="card-content">
<div class="product-category">footwear</div>
<h3 class="product-title">Aero Pulse Sneakers</h3>
<p class="product-description">Breathable mesh, cloud foam sole. Perfect for daily runs and urban walking.</p>
<div class="price-rating">
<div class="price">$89 <small>USD</small></div>
<div class="rating">
<span class="stars">★★★★☆</span>
<span class="rating-value">4.7</span>
</div>
</div>
<button class="btn-card" aria-label="Add to cart">🛒 Add to cart</button>
</div>
</div>
<!-- CARD 2 - smartwatch with discount -->
<div class="product-card">
<div class="card-img">
<img src="https://cdn-icons-png.flaticon.com/512/4358/4358353.png" alt="smart watch" loading="lazy">
<div class="badge green">−20% off</div>
</div>
<div class="card-content">
<div class="product-category">wearables</div>
<h3 class="product-title">Orbit Smart Watch</h3>
<p class="product-description">Heart rate, GPS, 7-day battery. Sleek AMOLED display & water resistant.</p>
<div class="price-rating">
<div class="price">$159 <small>USD</small> <span class="old-price">$199</span></div>
<div class="rating">
<span class="stars">★★★★★</span>
<span class="rating-value">4.9</span>
</div>
</div>
<button class="btn-card" aria-label="Add to cart">🛒 Add to cart</button>
</div>
</div>
<!-- CARD 3 - minimal backpack -->
<div class="product-card">
<div class="card-img">
<img src="https://cdn-icons-png.flaticon.com/512/4383/4383497.png" alt="modern backpack" loading="lazy">
</div>
<div class="card-content">
<div class="product-category">accessories</div>
<h3 class="product-title">Urbanite Backpack</h3>
<p class="product-description">Water-resistant, padded laptop sleeve (15"), comfortable ergonomic straps.</p>
<div class="price-rating">
<div class="price">$64 <small>USD</small></div>
<div class="rating">
<span class="stars">★★★★☆</span>
<span class="rating-value">4.5</span>
</div>
</div>
<button class="btn-card" aria-label="Add to cart">🛒 Add to cart</button>
</div>
</div>
<!-- CARD 4 - wireless earbuds -->
<div class="product-card">
<div class="card-img">
<img src="https://cdn-icons-png.flaticon.com/512/2970/2970240.png" alt="earbuds" loading="lazy">
<div class="badge">new</div>
</div>
<div class="card-content">
<div class="product-category">audio</div>
<h3 class="product-title">AuraBuds Pro</h3>
<p class="product-description">Active noise canceling, 30h battery, IPX4 sweat resistant, deep bass.</p>
<div class="price-rating">
<div class="price">$119 <small>USD</small></div>
<div class="rating">
<span class="stars">★★★★★</span>
<span class="rating-value">5.0</span>
</div>
</div>
<button class="btn-card" aria-label="Add to cart">🛒 Add to cart</button>
</div>
</div>
<!-- CARD 5 - casual hoodie -->
<div class="product-card">
<div class="card-img">
<img src="https://cdn-icons-png.flaticon.com/512/2523/2523864.png" alt="hoodie" loading="lazy">
</div>
<div class="card-content">
<div class="product-category">clothing</div>
<h3 class="product-title">Cozy Fleece Hoodie</h3>
<p class="product-description">Recycled cotton blend, relaxed fit, kangaroo pocket, premium organic dye.</p>
<div class="price-rating">
<div class="price">$49 <small>USD</small></div>
<div class="rating">
<span class="stars">★★★★☆</span>
<span class="rating-value">4.6</span>
</div>
</div>
<button class="btn-card" aria-label="Add to cart">🛒 Add to cart</button>
</div>
</div>
<!-- CARD 6 - ceramic coffee mug (eco) -->
<div class="product-card">
<div class="card-img">
<img src="https://cdn-icons-png.flaticon.com/512/2598/2598269.png" alt="coffee mug" loading="lazy">
<div class="badge green">eco</div>
</div>
<div class="card-content">
<div class="product-category">kitchen</div>
<h3 class="product-title">Artisan Ceramic Mug</h3>
<p class="product-description">Handmade stoneware, 12oz, dishwasher safe, minimalist matte finish.</p>
<div class="price-rating">
<div class="price">$24 <small>USD</small></div>
<div class="rating">
<span class="stars">★★★★☆</span>
<span class="rating-value">4.8</span>
</div>
</div>
<button class="btn-card" aria-label="Add to cart">🛒 Add to cart</button>
</div>
</div>
</div>
<div class="demo-note">
⚡ Fully responsive grid — resizing browser automatically adapts columns. Pure CSS + hover animations. Ready for CodePen.
</div>
</div>
<!-- tiny optional script: just to show interactive console feedback (non-intrusive) -->
<script>
(function()
// simple interactive feedback for demonstration purposes - does not affect design
const buttons = document.querySelectorAll('.btn-card');
buttons.forEach(btn =>
btn.addEventListener('click', (e) =>
e.preventDefault();
const card = btn.closest('.product-card');
const title = card?.querySelector('.product-title')?.innerText );
);
)();
</script>
</body>
</html>
Imagine a craftsman named Elias who spent months building the perfect leather bag. He takes a beautiful photo and puts it on his website. He writes the price, a lovely description, and waits for sales. responsive product card html css codepen
But nobody buys it.
Why? Because on a mobile phone, the photo was tiny, the "Buy" button was hidden off-screen, and the text was cramped. On a desktop monitor, the image was stretched and pixelated. Elias had a great product, but his "digital shop window" was broken.
This is the story of how we fix Elias's problem using Responsive Web Design. We are going to build a product card that adapts to its environment—tall and narrow on phones, wide and elegant on desktops.
.grid-container display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.5rem; padding: 2rem; max-width: 1400px; margin: 0 auto;.card background: #ffffff; border-radius: 1rem; overflow: hidden; transition: all 0.3s ease; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); position: relative;
.card:hover box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.2);
.card-badge position: absolute; top: 10px; left: 10px; background: #ef4444; color: white; padding: 4px 12px; border-radius: 20px; font-size: 0.75rem; font-weight: bold; z-index: 10; This is the fastest way to create a
img width: 100%; height: 220px; object-fit: cover;
.card-content padding: 1.25rem;
/* Responsive typography */ h2 font-size: clamp(1.2rem, 4vw, 1.5rem); margin: 0 0 0.5rem 0;
/* CodePen specific: Make it look gorgeous */ body background: #f3f4f6; font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
The magic line: grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)). This tells the browser: "Create as many columns as possible where each column is at least 280px wide, but if there is extra space, distribute it equally." No media queries required! Imagine a craftsman named Elias who spent months
Sometimes, on ultra-wide screens or mobile viewports, a horizontal scroll on row is more UX-friendly for related products.
.horizontal-scroll display: flex; overflow-x: auto; gap: 1rem; scroll-snap-type: x mandatory; padding: 1rem;.horizontal-scroll .card flex: 0 0 280px; /* Fixed width for scroll */ scroll-snap-align: start;
/* Hide scrollbar for cleaner look (Webkit) */ .horizontal-scroll::-webkit-scrollbar display: none;
We use semantic tags. article acts as the card container, figure handles the image, and section groups the text.
<div class="product-container"> <article class="product-card"> <!-- The Image Area --> <figure class="product-image"> <img src="https://images.unsplash.com/photo-1548036328-c9fa89d128fa?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80" alt="Vintage Leather Bag on wooden table"> <span class="product-badge">New</span> </figure><!-- The Content Area --> <section class="product-details"> <header> <h3 class="product-title">The Wanderer Rucksack</h3> <p class="product-subtitle">Handcrafted Vintage Leather</p> </header> <p class="product-description"> A durable and stylish companion for your weekend trips. Made with full-grain leather that ages beautifully over time. </p> <footer class="product-footer"> <div class="product-price"> <span class="price-current">$189.00</span> <span class="price-original">$230.00</span> </div> <button class="add-to-cart">Add to Cart</button> </footer> </section>
</article> </div>
Now for the magic. We need to style the card to handle different screen sizes.