Welcome to your sixth lesson! In our previous session, you created an excellent foundation for our e-commerce store by building a semantic and accessible HTML product card. While structurally sound, it's currently a plain, unstyled document.
Today, we will bring that structure to life. Our goal is to use CSS Flexbox and Grid to arrange storefront navigation, product cards, and a responsive catalog. These two modern CSS layout modules are the industry-standard tools for building any web interface, from simple components to complex, application-wide layouts. We'll explore the distinct strengths of each, using Flexbox for one-dimensional arrangement (like a navigation bar) and Grid for two-dimensional layouts (like our product catalog).
Setting Up Our Workspace
First, let's create the files we'll be working with. In your client folder, create a new file named catalog.html and another new file named styles.css.
Open catalog.html and paste in the following HTML. This structure includes a <header> for our navigation, a <main> element to hold our product catalog, and links our new stylesheet. It also includes several copies of the product card you built in the last lesson, wrapped in <li> tags as we previewed.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>E-Commerce Catalog</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class="site-header">
<div class="logo">MyStore</div>
<nav>
<ul class="nav-list">
<li><a href="#">Home</a></li>
<li><a href="#">Shop</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
<div class="cart-icon">Cart</div>
</header>
<main>
<ul class="product-grid">
<li>
<article class="product-card">
<img src="https://via.placeholder.com/300x400" alt="A gray placeholder image for a product.">
<div class="card-content">
<h2>Classic Tee</h2>
<p>$24.99</p>
<button type="button">Add to Cart</button>
</div>
</article>
</li>
<li>
<!-- Repeat the article block for 5-6 more products -->
<article class="product-card">
<img src="https://via.placeholder.com/300x400" alt="A gray placeholder image for a product.">
<div class="card-content">
<h2>Modern Jean</h2>
<p>$79.99</p>
<button type="button">Add to Cart</button>
</div>
</article>
</li>
<li>
<article class="product-card">
<img src="https://via.placeholder.com/300x400" alt="A gray placeholder image for a product.">
<div class="card-content">
<h2>Leather Jacket</h2>
<p>$149.99</p>
<button type="button">Add to Cart</button>
</div>
</article>
</li>
<!-- Add 3 more for a total of 6 -->
</ul>
</main>
</body>
</html>
Note: I've wrapped the text and button of your product card in a new <div class="card-content">. This grouping will help us with styling.
Now, open styles.css and add some basic resets and styles.
/* Basic Reset & Body Styles */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: system-ui, sans-serif;
line-height: 1.5;
}
ul {
list-style: none;
}
img {
max-width: 100%;
display: block;
}
With our setup complete, let's start arranging things.
One-Dimensional Layouts with Flexbox
Flexbox is designed for laying out items in a single dimension—either in a row or in a column. This makes it perfect for component-level layouts like navigation bars, form controls, or the contents of our product card.
The core idea is simple: you declare a parent element as a flex container, and its direct children become flex items. The container then gains powerful properties for aligning and distributing those items.
Flexbox - Learn web development | MDN
To understand the core model of Flexbox, read the introductory sections from the MDN guide.
Start by reading the introduction, which shows how display: flex immediately changes the layout. Then, carefully review the section on the flex model, paying close attention to the definitions of the main axis and cross axis. Understanding these two axes is the key to using Flexbox effectively.
Arranging the Storefront Navigation
Let's apply this to our <header>. We want the logo on the left, the navigation in the middle, and the cart icon on the right, all aligned neatly in a row.
The following video from Kevin Powell is a great practical guide to the alignment properties we need.
This video provides a clear, hands-on demonstration of how to use Flexbox's alignment and justification properties.
Watch the segment explaining the justify-content property from the main axis. Note the different values like space-between and center. Then, watch the segment on align-items from the cross axis, which controls vertical alignment.
Now, let's apply these concepts. Add the following CSS to your styles.css file.
.site-header {
display: flex;
justify-content: space-between; /* Distributes items along the main (horizontal) axis */
align-items: center; /* Aligns items along the cross (vertical) axis */
padding: 1rem 2rem;
background-color: #f8f9fa;
border-bottom: 1px solid #dee2e6;
}
.nav-list {
display: flex;
gap: 1.5rem; /* A modern way to add space between flex items */
}
If you open catalog.html in your browser, you'll see a perfectly arranged header. justify-content: space-between places the first and last items at the edges and distributes the remaining space evenly between all items. align-items: center ensures everything is vertically centered. We also made the nav-list itself a flex container to arrange the links horizontally with a gap.
Arranging the Product Card Content
Flexbox is also ideal for the internal layout of our product card. We want the content to fill the available space, with the "Add to Cart" button pushed to the bottom. We can achieve this by making the .card-content a flex container and changing its direction.
Flexbox - Learn web development | MDN
This reading covers how to change the flex direction and control how flex items grow or shrink.
First, read the section on Columns or rows? to learn about the flex-direction property. Then, review Flexible sizing to understand the flex property, which controls how items take up space.
Let's use a vertical flex layout inside our card. The key is to let the main content area (name and price) "grow" to occupy all available vertical space, which will push the button to the bottom.
Add this CSS to styles.css:
.product-card {
border: 1px solid #e9ecef;
border-radius: 8px;
overflow: hidden; /* Ensures the image corners are rounded */
display: flex; /* Make the card itself a flex container */
flex-direction: column; /* Stack its children (image and content div) vertically */
height: 100%; /* Make card fill the height of its grid cell (important for later) */
}
.card-content {
padding: 1rem;
display: flex;
flex-direction: column; /* Stack its children (h2, p, button) vertically */
flex-grow: 1; /* This is key! The content area will grow to fill available space */
}
.card-content h2 {
flex-grow: 1; /* This makes the h2/p area grow, pushing the button down */
}
.card-content button {
margin-top: 1rem; /* Add some space above the button */
padding: 0.75rem;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
Here, we have nested flex containers! The .product-card is a column flex container to stack the image and the content area. The .card-content is also a column flex container to stack its text and button. By setting flex-grow: 1 on the content area and the h2's parent (implicitly), we tell them to expand and fill the empty space, which elegantly solves our alignment problem.
Two-Dimensional Layouts with Grid
While Flexbox excels at single-axis layouts, CSS Grid is built for two dimensions: rows and columns. This makes it the perfect tool for our main product catalog.
The basic concepts are similar to Flexbox: you define a grid container, and its children become grid items.
This guide from web.dev introduces the essential terminology and properties for creating a grid.
Start with the Grid terminology section to familiarize yourself with terms like tracks, cells, and gaps. Then, read the section on Rows and columns to see how to define a basic grid structure with grid-template-columns and the flexible fr unit.
Creating a Responsive Product Catalog
Our goal is a grid of products that automatically adjusts the number of columns based on the available screen space, without writing a single media query. This powerful pattern is one of the main reasons CSS Grid is so popular.
Kevin Powell's video demonstrates this exact technique for a product grid.
Learn how to create a responsive CSS grid layout
This video walks through building a responsive product grid from start to finish.
First, watch how a basic grid is created using display: grid and grid-template-columns from this segment. Then, watch the crucial part where the layout is made responsive using the repeat(autofit, minmax()) pattern from this section. This is the most important technique in this part of the lesson.
Let's implement this powerful pattern. Add the following to styles.css:
main {
padding: 2rem;
}
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 2rem;
}
This one line of CSS is remarkably powerful:
repeat(auto-fit, ...): Tells the browser to create as many columns as can fit.minmax(280px, 1fr): Each of those columns must be at least280pxwide. If there's extra space left over, the1frtells the columns to share it, growing to fill the container.
When the container is too narrow to fit another 280px column, auto-fit will wrap it to the next row, automatically reducing the column count. Resize your browser window to see this magic in action!
Harmonizing Image Sizes
You'll notice one problem: if our product images had different dimensions, our grid would look messy. We can enforce a consistent shape for all images using aspect-ratio and object-fit.
Learn how to create a responsive CSS grid layout
This part of the video explains how to create consistently-sized images that don't get distorted.
Watch the section from this timestamp to see how aspect-ratio and object-fit: cover work together to create uniform, well-cropped images.
Let's apply this to our product card's image. Add the following rule to styles.css:
.product-card img {
aspect-ratio: 1 / 1.25; /* A rectangular ratio, taller than it is wide */
object-fit: cover; /* Behaves like 'background-size: cover', cropping to fit */
width: 100%;
}
Now all our product images will have the same aspect ratio, creating a clean, professional-looking grid.
Conclusion
In this lesson, you've mastered the fundamentals of modern CSS layout, a cornerstone skill for any web developer. You've learned how to choose the right tool for the job, using both Flexbox and Grid to build a responsive and professional-looking storefront layout.
Here are the key takeaways:
- Flexbox is best for one-dimensional layouts, like arranging items in a navigation bar or stacking content within a card. Key properties include
display: flex,flex-direction,justify-content, andalign-items. - CSS Grid is designed for two-dimensional layouts, making it ideal for page-level structures and catalogs.
- The
repeat(auto-fit, minmax(min, 1fr))pattern is a powerful technique for creating fully responsive grids without media queries. - Flexbox and Grid work together beautifully. We used Grid for the overall catalog layout and Flexbox for the internal arrangement of each card.
You now have a responsive catalog page. In our next lesson, we'll refine this layout further by applying mobile-first media queries to adapt the storefront across common screen sizes, ensuring a polished experience on any device.