Do you want to showcase your products, images, or any content in an organized and adaptable way across all screen sizes? Creating an effective CSS Responsive Product Grid is essential for modern web design. This tutorial provides a simple yet powerful solution using CSS Grid. It helps you build a flexible layout that looks great on desktops, tablets, and mobile phones, enhancing the user experience on your e-commerce site or portfolio.
How to Create a CSS Responsive Product Grid
Add Header Assets
To begin, include a reset stylesheet in the head section of your HTML document. This helps to ensure consistent styling across different browsers.
<link rel="stylesheet" href="https://public.codepenassets.com/css/reset-2.0.min.css">
Build the HTML Structure
Next, set up the basic HTML for your product grid. This structure defines the container, the product list, and individual product cards.
<div class="container">
<h3>
Example Catalog Layout with <span>CSS Grid</span>
</h3>
<ul class="grid">
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=550" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=551" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=552" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=553" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=554" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=555" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=556" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=557" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=558" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=559" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=560" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=562" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=563" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=564" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=565" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=566" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=567" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=568" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=569" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=570" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=571" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=572" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=573" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=574" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=575" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=576" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=577" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=579" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=580" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
<li class="card">
<a class="card__link" href="#"><img class="card__image" src="https://picsum.photos/400?image=581" />
<div class="card__text">
Example Product Name
</div>
<div class="card__price"></div>
</a>
</li>
</ul>
</div>
<footer>
Built for SwiftOtter.
</footer>
<script src="./script.js"></script>
Apply CSS Styling
Now, add the CSS to make your product grid responsive and visually appealing. This code uses CSS Grid for the layout and includes styles for product cards and responsiveness.
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-gap: calc(2em + 2vh) calc(1.5em + 1vmin);
grid-auto-flow: row dense;
}
.card__image {
display: block;
max-width: 100%;
}
/* ==== Styles Related to the callout ==== */
.grid .card:nth-child(14) {
grid-column: 1/-1;
grid-row: span 2;
align-self: center;
}
@media (min-width: 712px) {
.grid .card:nth-child(14) {
grid-column: 2/-2;
}
}
.grid .card:nth-child(14) .card__image {
margin: 0 auto;
-o-object-fit: cover;
object-fit: cover;
}
@media (min-width: 712px) {
.grid .card:nth-child(14) .card__image {
height: 100%;
}
}
/* ==== Additional Styles not related to grid layout ==== */
.container {
display: grid;
grid-template-columns: minmax(1em, 1fr) minmax(-webkit-min-content, 1200px) minmax(1em, 1fr);
grid-template-columns: minmax(1em, 1fr) minmax(min-content, 1200px) minmax(1em, 1fr);
grid-template-areas: "l-gutter heading r-gutter" "l-gutter content r-gutter";
grid-row-gap: 1em;
}
.grid {
grid-area: content;
margin-bottom: 2em;
}
.card__link {
text-align: center;
color: inherit;
text-decoration: none;
}
.card__link:hover {
color: #2d2d2d;
}
.card__link:hover .card__image {
transform: scale(1.04);
-webkit-clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 90%, 0 100%);
clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 90%, 0 100%);
}
.card__link:hover .card__text {
transform: rotate(2deg) translate3d(3%, 1%, 0) scale(1.02);
}
.card__link:hover .card__price {
transform: rotate(-2deg) translate3d(-3%, -1%, 0) scale(1.02);
}
.card__image {
-webkit-clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 100%, 0 100%);
clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 100%, 0 100%);
transition: transform 200ms ease-out, -webkit-clip-path 200ms ease-out;
transition: transform 200ms ease-out, clip-path 200ms ease-out;
transition: transform 200ms ease-out, clip-path 200ms ease-out, -webkit-clip-path 200ms ease-out;
}
.card__price {
font-weight: 600;
transition: transform 300ms ease-out;
}
.card__text {
padding: 1em 0 0.5em;
font-weight: 200;
transition: transform 300ms ease-out;
}
h3 {
grid-area: heading;
font-size: calc(1.25rem + 2vw);
padding: 1em 0 0.5em;
line-height: 1.3;
max-width: 18ex;
text-shadow: 0 0 1em rgba(255, 255, 255, 0.5);
}
@media (min-width: 1000px) {
h3 {
font-size: 2.5rem;
}
}
h3 > span {
font-weight: 700;
}
footer {
text-align: center;
background-color: #4448;
color: #fff;
padding: 2em;
margin-top: 2em;
}
body {
font-family: system-ui;
font-size: 16px;
color: #555;
}
body::before {
content: "";
width: 120%;
height: 40vh;
position: absolute;
left: -20%;
top: -20%;
transform: rotate(-10deg);
background-color: #ffeb3b;
z-index: -1;
}
Add JavaScript for Dynamic Content
Finally, include this JavaScript code. It populates example product names and prices, making the grid dynamic.
// Used to populate different values for the various items
const exampleNames = ["Helena Hooded Fleece", "Stellar Solar Jacket", "Ingrid Running Jacket", "Nadia Elements Shell", "Neve Studio Dance Jacket", "Gabrielle Micro Sleeve Top", "Layla Tee", "Elisa EverCool™ Tee", "Juliana Short-Sleeve Tee"];
document.querySelectorAll('.card__price').forEach(price => {
let randomPrice = Math.floor(Math.random() * 100) + 1;
price.textContent = `${randomPrice}.99`;
});
document.querySelectorAll('.card__text').forEach((name, i) => {
name.textContent = exampleNames[i % exampleNames.length];
});
document.querySelector('.grid .card:nth-child(14) img').src = `https://picsum.photos/600/450?image=564`;
That’s all! Hopefully, you have successfully created a CSS Responsive Product Grid. If you have any questions or suggestions, feel free to comment below.







