October 15, 2024
CSS container queries & units
The CSS container query is in the 2023 Baseline
This means it works accross Chrome, Edge, Safari and Firefox.
However, container query units aren't in the baseline yet, even though they're just as widely available as container queries. You can check their support at https://caniuse.com/css-container-queries and https://caniuse.com/css-container-query-units).
The basics
Container queries offer a new way to change the layout of your components responsively. Instead of targeting a media size, you can target the size of a container instead.
Container query units are relative to the container, unlike units such as vw and vh., which relate to the entire width and height of the page.
To use container queries and query units, you need to define a container somewhere on an ancestor of the element where you want to apply these queries and units. The syntax is similar to media queries and viewport units:
body,
.container {
container-type: inline-size;
}
.child {
width: 100%;
@container (min-width: 768px) {
width: 50%;
}
}
h2 {
font-size: 4cqw;
}
For a container query to work, you need an ancestor with a container-type set. More details can be found at https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment/Container_queries#using_container_queries. This is why the body tag also needs a container-type property.
When the child element of the container is outside of the container, the body tag acts as the container, behaving similarly to a media query. When it's placed inside the container, it responds to the container's width instead.
Example 1 - The Basics
In this first example, you have four containers:
The first container has an image component with five images. It looks just fine.
The second container includes both a text component and an image component. The images appear a bit too small because you're using the same layout as when the image component alone fills the entire container width.
In the third container, the layout is adjusted using a container query instead of a regular media query, making the images larger – just perfect!
The fourth example demonstrates what can go wrong when trying to use a container query without an ancestor that has a containment context. Remember to set a container-type on the body, #app, or wherever else you prefer.
With this approach, you get a nice responsive layout where the image component can be used alone or alongside a text component, adjusting nicely to the container they're placed inside.
Example 2 - Using Container Query Units
In this example, you have four containers that demonstrate what you can do with container query units:
The first container has a text component, and everything looks fine.
The second container includes both a text and image component, each taking up an equal part of the container horizontally. The headline looks a bit large since it's set in the vw (viewport width) unit.
In the third container, the headline is adjusted to use the container query width unit (cqw), which is better.
In the last container, the font size for the paragraphs and padding inside the component also change responsively according to the container's size.
You might want to view the results in CodePen to see the difference clearly 😉
As you can see in the last example, it doesn’t always make sense to replace every media query with a container query. The text can become too small, and padding set in cqw inside the container might cause layout issues when you want the left and right sides of the components aligned.
In the next example, you’ll see when it does make sense to adjust the padding.
Example 3 - Queries and Units combined
In this final example, you'll explore how container queries and query units can be combined for a better layout in a modal.
Imagine you have some content loaded into a modal that occupies only part of the screen. This content is based on the same components used elsewhere on the page, so it would be great if you didn’t have to change too much of the CSS when the content is placed in the modal.
There are two modals in this example:
In the first modal, nothing has been changed, and the responsive content relies on a regular media query. The headlines and paddings seem a bit too large, and the layout with text and images side by side appears cramped at certain screen sizes.
In the second modal, the headlines and paddings are adjusted to use the cqw unit, and the responsive layout uses a container query instead of a media query.
As in example 2, you may want to switch to the result view in CodePen to observe the difference.
Again, this approach gives you a great responsive layout, where sizes adjust using the cqw unit and the layout changes with a container query.
Conclusion
These are just a few examples of the changes you can make using container queries and container query units. There’s more to explore:
Different container-types (size, inline-size, normal).
Naming containers and targeting them specifically in queries.
Various units (cqh, cqw, cqi, cqb, cqmin, and cqmax). The cqmin and cqmax units respond to the smaller or larger value of either cqi or cqb.
I recommend you take a look at the specs: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment/Container_queries.
What I find exciting about container queries and units is that when building websites or apps with a JavaScript framework like Vue on a headless foundation, you can create flexible components that load asynchronously and fit almost any container you place them in. It may be more time-consuming initially, but as you adapt and get familiar with it, you’ll quickly know where to be cautious and where to dive right in.
If you've got some great examples with other ways of using the container queries and units and want to share - please let me know at [email protected] and I'll update the post and credit you.