creatures.sh

CSS Container Queries

A photo of Lazar Nikolov

nikolovlazar


Aug 30 ・ 4 min read

CSS Container Queries

Unlike Media Queries, which let you apply styles to an element based on the viewport size, Container Queries let you apply styles to an element based on its own size. Talk about next level responsive design! And the best thing is, it’s supported by all modern browsers! Let’s say you want a card’s layout to be horizontal if it has at least a certain width, and switch to vertical when it gets narrower. Here’s an example:

See the Pen CSS Container Queries by Lazar Nikolov (@nikolovlazar) on CodePen.

Containment context

Looking at the example, we can see that our article.post-card has a container property with a value of post-card / inline-size. This declares a containment context on our post card element. The container is a shorthand property that sets the container-name to post-card and the container-type to inline-size. The inline-size value declares the containment context on the inline axis of the container. This means that you can only define styles based on the width of the container. If you also want to define styles based on the height, you can use the size value.

Bear in mind that when you declare a container to a certain element, it will prevent it from being sized based on its contents. This goes for both size and inline-size. To provide size to the “containerized” element, you would need to either define it through its parent (flex and grid stretch by default) or its display (block also stretches by default), or set its width or height explicitly. Setting the container-type to size will collapse its height, while setting it to inline-size will collapse its width.

Another thing to have in mind is that you can’t use an inline element as a container. If you were to define a span as a container, you could, but you’d have to make it a non-inline display. Rule of thumb: any element that’s not inline can be made into a container.

Container query

Check out line 40. We set the .content element’s flex-direction to column. On smaller sizes we want the image and text to be one on top of the other, but if we have enough horizontal space we can actually put them one next to the other, or set the flex-direction to row. That’s a use case for a container query! Scroll down to line 96:

@container post-card (min-width: 512px) {
  ...
}

This is how we define a container query. With this line, we’re basically telling CSS “when the post-card container (not element with class) has at least 768px of width, apply these styles (…)”. The top level scope is the article.card element. We should take that in consideration when writing the selectors. On line 99 we redefine the .content element’s flex-direction to row. That’ll make the image and text to flow horizontally, and if we expand the viewport enough we’ll see that the card’s content changes direction. Notice that if we change the selector to article.post-card div.content it won’t work, even though it’s a perfectly valid selector, because it would expect to find an article.post-card inside of the article.post-card element and we both know that’s wrong. But following this example, we can redefine any property of any descendant of our article.post-card. That’s the beauty of it!

Container query units

Along with the new @container syntax, we also get brand new values that are relative to the container size. Here are they:

  • cqw is 1% of the container’s width
  • cqh is 1% of the container’s height
  • cqi is 1% of the container’s inline size
  • cqb is 1% of the container’s block size
  • cqmin and cqmax are the smallest and largest (respectfully) value of either cqi or cqb

So, if we wanted to set something to be the 3% of the container’s width for example, we would set it to 3cqw. Scroll all the way down to line 123, 128 and 133, and you’ll see that the text elements are being set to a certain percentage of the container’s inline size. Try changing the size of the card and you’ll see that the font size grows and shrinks with the card. This might not be a real-world use case, but you get the gist 😁.

Conclusion

So there you have it! Container Queries! How cool are they? You can use them to define responsive elements that react not based on the viewport’s size, but based on the space they’re given, regardless of the viewport size. That means that you can have two instances of the same component on a page, but because of the different space they’re given, they’ll appear differently. Check out the creatures.sh blog page. The featured post card is the same component as the post cards in the grid below. That card is the card from this example, but used in production. If you want to see more use cases, check out this article (takes you to CSS Tricks).

Tags:

#CSS
An image of a creature from creatures.sh

Want to publish your own article?

Learn how