Tom's dev blog

Design systems, CSS and font on the web

A guide to CSS Container Queries

A modern approach to repsonsive components

Right now (September 2021) container query is still an early stage specification.
It is only supported by Chrome with a flag and the implementation might change in the future.
But there is Polyfill based solution that we through at the end of the post.

In CSS, we can use media-queries to adapt the layout based on the viewport size. It allows us to adapt the layout based on the screen size of the user.

We take it for granted but back in the days this was a life changer!

But we can still do better.

The use case

We think way more in terms of components nowadays and we'd like components to behave based on the space they've been given, not the layout size.

Let's say we have a card that supports a narrow and a compact layout.

Wouldn't that be cool if CSS could switch this layout based on the parent width?

Two card components. One uses an horizontal layout and the other a vertical one.

Selecting the layout based on the viewport doesn't make a lot of sense here. What matter is how much room is available for the card, the container.

This open to a lot of neat things! We can now let our component adapt their layout seamlessly 🤙

The code

Container queries needs the container to have a container-type property. It defines which query type we can use. For example to query the width we'll put the following on the container:

.container {
  container-type: inline-size;
}

We can now use @container on our component:

@container (min-width: 600px) {
  .card {
    display: flex;
  }
}

And that is basically it, that simple.

Have a look at that demo:

See the Pen Unknown Pen on CodePen.

Polyfill to the rescue

Right now, container queries are not supported in any browser.

But hold on, we can still make it work. I found the easiest solution to be Jonathan Neal's CQFill.

We will need to make changes to the CSS. Let's add a --css-contain: layout inline-size; to the container and we'll make a new selector with @media --css-container and (min-width: 400px) after the @container one. There is also a PostCSS plugin for that.

Our code now look like this:

.container {
  container-type: inline-size;
  /* For the Polyfill */
  --css-contain: layout inline-size;
}

@container (min-width: 600px) {
  .card {
    display: flex;
  }
}

/* For the Polyfill */
@media --css-container and (min-width: 400px) {
  .card {
    display: flex;
    gap: 16px;
  }
}

We'll also import the Polyfill itself in our code using:

<script src="https://unpkg.com/cqfill"></script>

And that will make container queries work on any browser!

For more information, check out the CQFill repository.

This is everything needed to get started with container queries, congratulations 🥳

If you want to apply your fresh knowledge, a good challenge is to create a blog post component that can be used in the main list, in the sidebar and in the recommended post list.

I'm Tom Quinonero, I write about design systems and CSS, Follow me on twitter for more tips and resources 🤙