Readers like you help support MUO. When you make a purchase using links on our site, we may earn an affiliate commission. Read More.

For a long time, media queries were the only way to make UI designs responsive on different screen sizes. But even that had its limitations. One of the biggest issues with using media queries was that you could only style an element in response to changes in the screen size, not its nearest container element.

Container queries were introduced to solve this problem. They have also surged with the popularity of frameworks like React and Vue.js which work by creating modular UI "components". Learn how to use container queries to create responsive elements in your CSS.

MAKEUSEOF VIDEO OF THE DAY
SCROLL TO CONTINUE WITH CONTENT

The code used in this article is available in this GitHub repository and is free for you to use under the MIT license.

Why You Should Use CSS Container Queries?

To understand the importance of container queries, let's use an example that makes it easier to grasp the concept. But first, you need to clone the starter code from this GitHub repository.

Once you've successfully cloned the repo, run the code. You'll find a webpage similar to the following image:

Screenshot of page in full screen

Here you have a grid layout comprising two columns: the main section and the sidebar. The main section looks okay, but the sidebar (which is much smaller than the main content) looks a bit squished.

The layout is responsive. When you shrink the browser, you can see that the card transforms into a vertical column:

Screenshot of page as in shrinked form

In other words, when the content starts to become unreadable, the layout transforms into a vertical column where the image is stacked on top of the content. This effect comes as a result of the media queries, which is the only way you can determine the size of elements based on the entire size of your screen.

In this case, whenever your screen is less than 800px, you stack everything on top of each other using Flexbox alignment. On larger screens, we place the content side-by-side:

 @media(max-width: 800px) {
  .card {
    flex-direction: column;
  }
  .card-header {
    width: 100%;
  }
}

For the longest time, media queries have been one of the main web design principles for creating responsive layouts with CSS (and it's been good enough for most things). But you're bound to run into scenarios where media queries just won't be enough, or won't be a convenient solution at least.

One of those scenarios is when you have a sidebar (as we do in the above example). In these cases where you have a sidebar, you'd have to directly select the sidebar card and try to make it smaller:

 .sidebar .card {
  /* Make the sidebar card smaller */
}

@media(max-width: 800px) {
  /* Style the page when the screen is narrower than 800px */
}

It can be quite complicated if you're working with lots of elements because you have to manually select all the elements and resize them. You'd end up with more code and extra complexity.

This is where container queries could be useful. Instead of being forced to use your viewport as your sizing, you can use any element on your page as a container. Then that container can have its own widths on which you'd base your media queries.

How to Create a Container Query

To create a container query, you'd start by targeting the element you want to use as a container (in this case, the main section and sidebar). Inside the block, you need to set the container-type to inline-size:

 main, .sidebar {
  container-type: inline-size
}

When you save your CSS file, nothing will change on the page. But now you can use container queries to resize and restyle the cards nested within the main section and the sidebar section. In the following container query, you're changing the cards to vertical columns on screens that are 500px wide or less:

 @container(max-width: 500px) {
  .card {
     flex-direction: column;
  }
  .card-header {
    width: 100%;
  }
}

This is going to work as a normal media query. But instead of measuring the size of your screen, you're measuring the size of your containers (main and sidebar sections). So now when your container is 500px or more, you use the horizontal view. Otherwise, you use vertical (default for flexbox).

Screenshot of page using container queries

From the above image, you can see that the sidebar takes a vertical form because it's smaller than 500px. Whereas, the main content retains its horizontal layout because it is larger than 500px. If you shrink your browser down, your sidebar and main content will both use the vertical alignment when they reach 500px or less.

The container query is incredibly powerful because it allows you to resize things based on the container instead of the entire browser's width. This is especially useful when dealing with components (such as in React or Vue).

With container queries, you can easily resize your UI components based on their container, allowing you to create completely self-contained components.

Naming Containers

When you create a @container query, it first looks for the container of the element you're targeting within the query. In our case, this would be the main container and the sidebar container.

And even if the cards were inside another container, it would just ignore the other containers and only choose the closest container to itself. This is part of a broader CSS concept known as CSS selectors.

In the following example, we've turned the body element into a container:

 body {
  container-type: inline-size;
}

Now we have three separate containers: body, main, and aside section. By default, the cards we're targeting in the container query are closer to the main section or sidebar than to the body. So it uses the main and sidebar sections as containers for the container query.

To override this behavior, you need to do two things. First, you need to give your body element a container name:

 body {
  container-type: inline-size;
  container-name: body;
}

Then, when you create your container query, you need to specify the container name after @container.

 @container body (max-width: 1000px){
  /* CSS rules that target the body container */
}

This is useful if you want to use a specific element as a container rather than the closest container to the element you're targeting. In other words, you can select any specific container and fine-tune your layout.

Container Units

Another great feature about containers is that you can use container units. These units work just like viewport units (they're all the exact same type of units). However, container units use cqw (for setting width) and cqh (for setting height). These units determine the exact width and height of your container.

Learn More About CSS Media Queries

CSS container queries allow you to use specific elements as reference points for your media queries. This technique is quite handy for creating modular, self-contained elements that can stand independently regardless of the container they're in. But container queries use the same principles as media queries, and this is something you should master if you want to be a top one percent CSS developer.