Container queries are live (in Chrome)!
Tags: css, beginners
Published: 2022-09-08 02:34:00

---
title: Container queries are live (in Chrome)!
published: true
description: Container queries have landed in Chrome. Here's a quick overview.
tags: css, beginner
---

Update September 14, 2022: Safari 16 now also supports container queries! 
***
Chrome 105 rolled out some pretty exciting CSS support updates including long-awaited container queries!

## What are container queries?

Container queries are a new type of CSS query that, like many use cases for media queries, allows us to define styles based on a defined size. However, where `@media` encompasses the width of the environment—viewport or user settings like zoom—the new `@container` allows us to target specific elements on the page.

For a potential use case, let’s look at the related news stories section of [an article on the New York Times’ website](https://www.nytimes.com/2022/09/07/technology/apple-new-iphone-watch.html).

Here we have two columns: one wide column and one narrow column. The wider column includes a flex layout with multiple rows of three thumbnails and headlines (let’s call these headline and thumbnail sets “cards”). The narrower column includes a text-based list of links to the most popular stories. As I adjust the size of my browser window to be smaller, the two columns also change; the flex layout contained in the larger column reduces to show multiple rows of two cards instead of three.

![Screenshots of the “More in…” section of a  New York Times article showing the flex layout change the number of cards in a row. ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4dl9s6h18daikq6rkyp4.png)

(There’s an empty space in both of these screenshots because of my ad blocker. 🙃)


Currently, this is achieved with media queries. The individual cards are given a `max-width` that increases or decreases depending on the viewport’s width in pixels. 

```css
.card {
		max-width: 48%;
}

@media (min-width: 768px){
	.card {
		max-width: 32%;
	}
}
```

This works fine here, but what if this flex container of cards had more applications? Maybe a content author could insert our flex container into both narrow and wide columns. Currently, we only have the one media query for a `min-width: 768px`, but that would not be enough to make the cards look good in a significantly narrower column. 

And just think if our imaginary stakeholders wanted even more options: one, three, four column layouts that have to fit our flex container. Our edge cases are going to quickly spiral out of control as we’ll have to manually test and write out every possible viewport width combination as a media query. Instead of doing that, though, we can use container queries to scope these variations to the width of the container itself.

```css
.card-container {
	container-type: inline-block;
}

.card {
		max-width: 48%;
}

@container (min-width: 420px) {
	.card {
		max-width: 100%;
	}
}

@container (min-width: 680px) {
	.card {
		max-width: 32%;
	}
}
```

Note that we’re only styling the child `.card` selector within the container query. `@container` does not allow us to style the container itself. To apply responsive styles to the container element itself, we’ll need to still use `@media`.  Technically we could use *another* parent container, but if we need this flex container to have a variety of applications, nesting `@container` queries would bring us back to the busy work of working out every possible edge case of parent component.

With the continued popularity of component-based design systems and UI component libraries like Storybook, container queries allow us to be more consistently modular and flexible in our code. 

## container-type

The key to getting a container query to work is adding a `container-type` property to the element you wish to enable as a container. This will also allow the container to show up in [Chrome DevTools](https://developer.chrome.com/docs/devtools/css/container-queries/).

In the [latest working draft](https://www.w3.org/TR/2022/WD-css-contain-3-20220818/), `container-type` can take three potential values:

1. `normal`: the initial value/assumed default. This means the element will not be treated as a queryable container. 
2. `size`: establishes the element as a query container for size queries on both the inline (horizontal) and block (vertical) axis. 
3. `inline-size`: establishes the element as a query container for size queries on the inline (horizontal) axis. 

`inline-size` is the one you’ll probably see the most in early examples, and it’s the one I used in my [codepen](https://codepen.io/heyitsstacey/full/rNvaPMG). It works the way you’re probably used to working with media queries where it is relative to the width of the container. 

## container-name

You may find yourself wanting to establish multiple containers on a page with different styles. In this case, you’ll want to use the `container-name` property. This takes any string as a value and will allow you to specify which container you’re querying: 

```css
.card-container {
	container-type: inline-block;
	container-name: card-container
}

@container card-container (min-width: 420px) {
	.card {
		max-width: 100%;
	}
}
```

In this example, I’ve used the class name as the `container-name`, but that is by no means a requirement. It can be any unique, single-word string you need. As for best practices, while it’s still early days, the current draft uses kebob case (dashes) in [its examples](https://www.w3.org/TR/css-contain-3/#container-name).

## Size container features beyond width

In the examples above, I wrote my container queries using a `min-width` and pixel value for my size feature, but we’re not limited to that format. Let’s look at this example from the working draft: 

```css
main {
  container-type: size;
  container-name: my-page-layout;
}

.my-component {
  container-type: inline-size;
  container-name: my-component-library;
}

@container my-page-layout (block-size > 12em) {
  .card { margin-block: 2em; }
}

@container my-component-library (inline-size > 30em) {
  .card { margin-inline: 2em; }
}
```

Recall that “inline” refers to the horizontal sizing while “block” is the vertical. In the example above, `main`—named `my-page-layout`—has the container-type of `size` (both block and inline) while `.my-component`—named `my component-library`—has an `inline-size` (just inline). Therefore, in their named container queries, `@container my-page-layout (block-size > 12em)` will apply with a container height larger than `12em`, whereas `@container my-component-library (inline-size > 30em)` will apply with a width larger than `30em`. 

In future iterations, we may be to write size container queries in respect to aspect-ratio as well. 

## Limitations

As you may have guessed from multiple references to the working draft, `@container` is not universally supported yet. It is available in only the newest version of Chrome and Chromium-based Edge (partially), but is not yet in FireFox or Safari. Keeping an eye on [CanIUse.com](https://caniuse.com/?search=container-type), we see support is slowly but surely rolling out, as it’s now in the latest Safari Technology Preview. You will probably find yourself using `@media` in most cases for a little while longer, but it’s exciting to see such mainstream progress on its adoption.

***
*Posted late at night (for me) and edited with fresh eyes in the morning; cross-posted to my site.*