Product Layout With The CSS Grid

shopping bag logo

CSS Grid introduction

The CSS Grid module is used to create grid-based layouts, just as we have with our products area:

index page layout

Since we can control both the rows and columns it is described as a two dimensional layout system. This is in contrast to the CSS flexbox that deals with only one direction at a time.

Styling products

The index.html page has products inside of a div container, this will be the parent element to set the grid properties. Inside, each product (currently only 1 example) is an article element, these will be the child items. Update the elements below to include class names:

<!-- index.html -->
<div class="product-grid">
  <article class="product-card">
    <section class="product-image">
      <img
        src="images/t-shirt-blue.png"
        alt="blue t-shirt with short sleeves"
        class="product-image"
      />
    </section>
    <section class="product-details">
      <h3>Stylish long-sleeve t-shirt in blue / medium</h3>
      <p>A stylish long sleeve blue t-shirt, in size medium.</p>
      <p class="price">$20.95</p>
    </section>
  </article>
</div>

You may also want to create more products for testing (within the above container). This is optional as we will generate more products later using JavaScript.

Begin by adding some styling to the product card:

/* add to existing styles.css file */
.product-card {
    cursor: pointer;
    border: 1px solid #dde;
    border-radius: 3px;
    display: flex;
    flex-direction: column;
}

/* Hover effect for product cards */
.product-card:hover {
    transform: scale(1.02);
    box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.1);
}
  • cursor: pointer: Setting the cursor can give the user a visual clue as to what action can be taken. The pointer changes the mouse cursor to be a pointing hand when moving over this area, often indicating a link.
  • A 1px wide, solid border is added around the product, with a 3px rounded corner (border-radius).
  • We use the flexbox to set the content direction to be vertical using flex-direction: column.

CSS transforms

There is also a property used called transform which is used to apply transformations to elements. The scale function is added to scale/resize an element using one or two values:

  • scale(1.1): One value will scale the element's width and height. A value of 1 is the original size.
  • scale(0.5, 1): Width and height can be specified individually. If both are equal, scaling will be uniform. This will reduce the width by half, and retain the original height.
ValueVisual
transform: scale(1.1);
transform: scale(0.5, 1);

The above example is applied directly to the element to scale, the difference is we apply when the mouse hovers over the product (.product-card:hover). This can appear to look 'jumpy' and it can often help to make the transform smoother. We can do this by using the transition property:

.product-card {
  cursor: pointer;
  border: 1px solid #dde;
  border-radius: 3px;
  display: flex;
  flex-direction: column;
  /* add the transition */
  transition: transform 0.3s ease-in-out;
}

The transition property can transition between two states of an element. Such as a width transitioning from 100px to 200px. We apply to the transform property to control the scaling. This transition also has a duration in seconds, which we set to 0.3s. Ths final value we use is ease-in-out to slowly ease in the transition, speed it up, and slow down to complete. Values of ease-in and ease-out are also available to control individually.

The grid container

Create a grid container by setting the display property on the parent element, and style the product images:

.product-grid {
    display: grid;
}

/* Style for the product image */
.product-image {
    width: 100%;
    height: 200px;
    background-size: cover;
}

Setting the image width to be 100% of the container will allow the image to resize with the product.

Columns and rows

This will not yet change the layout as we need to declare the number of columns or rows. Columns are set using grid-template-columns:

/* creates 3 columns at 20% width */
grid-template-columns: 20% 20% 20%;
/* creates 2 columns at 1fr */
grid-template-columns: 1fr 1fr;
/* creates 4 columns at 300px wide */
grid-template-columns: 300px 300px 300px 300px;

The fr unit used above is a fractional unit. A value of 1fr 1fr will create two columns and calculate an equal width, 1fr 2fr will also create two columns but the second will try to take up twice the available width.

The repeat() function can also be used to repeat columns, add this to the product-grid:

.product-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
}

This will create three columns at 1fr wide.

To set the height of the rows there is the grid-template-rows property. Row heights can be specified individually, or by using the repeat() function. This will not be added to our project to allow rows to be determined by the product height.

Grid gaps

The gap property sets the gap size between rows and columns:

.product-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
}

The gap property is a shorthand for row-gap and column-gap, and row and column can also be set individually using two values, such as gap: 1rem 40px.

Final product styling

Complete the product styling with the following:

/* styles.css */
.product-details {
    padding: 1rem;
    display: flex;
    flex-direction: column;
    justify-content: space-evenly;
}

.product-details h3 {
    margin: 0 0 0.5rem;
    font-size: 1.25rem;
    color: #2d877d;
}

.product-details p {
    font-size: 0.875rem;
    color: #666;
}

.product-details .price {
    font-size: 1.25rem;
    font-weight: bold;
    color: #3d5944;
}