Responsive Image Grid with CSS Container Queries and CSS Custom Properties

Stefan Kandlbinder
4 min readFeb 26, 2023

Creating a responsive image grid based on CSS Container Queries and CSS Custom Properties

Responsive Image Grid

Prerequisites

If you are totally unfamiliar with the concept of CSS Container Queries, head over to the corresponding mdn web docs site CSS Container Queries.

Browser Support
https://caniuse.com/?earch=container%20queries%20size

Introduction

With the ability to combine CSS Custom Properties and CSS Container Queries, we are finally able to do something, which was only possible with the help of JavaScript and Resize Observer— Till Now.

What we are building

We are building a simple reusable mobile-first image grid component which should behave like this:

  • 3-column layout starting at a container min-width of 0px
  • 4-column layout starting at a container min-width of 320px
  • 6-column layout starting at a container min-width of 480px
  • 10-column layout starting at a container min-width of 768px
Responsive Image Grid

Let's start with the HTML and the CSS:

<div class="size-container">
<div class="image-grid">
<div class="image-grid-item"></div>
<div class="image-grid-item"></div>
...
</div>
</div>
.size-container {
container-type: inline-size;
container-name: size;
}

The surrounding size-container is responsible for setting the different states of our grid, dependent on its width. I am going into details a bit later.
The image-grid and image-grid-item elements are representing the grid and its corresponding items.

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

.image-grid-item {
aspect-ratio: 1 / 1;
width: 100%;
background: gray
}

The CSS Custom Property — image-grid-columns is responsible for the different column layouts of our grid as defined within the grid-template-columns CSS property.

Since we haven't applied any container queries, we are ending up with a repeating grid of 3 columns, where every item is scaling up to 100% based on the width of the surrounding container:

Default Grid Behavior

According to our mobile-first strategy, we define our first container break point at 320px.

@container size (min-width: 320px) {
.image-grid {
--image-grid-columns: 4;
}
}

This means, that at a minimum container (not viewport!) width of 320px, we are setting the --grid-columns property to 4.

This CSS Container Query in combination with the CSS Custom Property is leading to the following grid behavior:

Switching From 3 Columns To 4 Columns

At a minimum container width of 320px, our 3-column layout is switching to a 4-column layout.

Switching from 4 columns to 6 and from 6 to 10 is just straightforward:

@container size (min-width: 480px) {
.image-grid {
--image-grid-columns: 6;
}
}

@container size (min-width: 768px) {
.image-grid {
--image-grid-columns: 10;
}
}

Final result

A responsive mobile first image grid depending on the width of its surrounding container
Single Grid

Now, with a little help from CSS Container Queries and CSS Custom Properties, we are able to create reusable responsive components without writing any JavaScript.
In this simple example, we were just scratching the surface.
I hope you were able to find some inspiration, and you are now ready and motivated to create your own responsive components with a little help from CSS Container Queries and CSS Custom Properties.

TU ES!

If you want to play around, just head over to my codepen implementation.

To get the full picture of CSS Container Queries, just place our image grids in a surrounding grid column layout.
Dependent on the surrounding size-container width, the grid changes according to our container breakpoints.

Multi Grid (Grid In A Grid)

Cheers,
Stefan

--

--