Next Gen CSS: @container
Publikováno: 11.5.2021
Chrome is experimenting with @container
, a property within the CSS Working Group Containment Level 3 spec being championed by Miriam Suzanne of Oddbird, and a group of engineers across the web platform. @container
brings us the ability to …
The post Next Gen CSS: @container appeared first on CSS-Tricks.
You can support CSS-Tricks by being an MVP Supporter.
Chrome is experimenting with @container
, a property within the CSS Working Group Containment Level 3 spec being championed by Miriam Suzanne of Oddbird, and a group of engineers across the web platform. @container
brings us the ability to style elements based on the size of their parent container.
You can think of these like a media query (@media
), but instead of relying on the viewport to adjust styles, the parent container of the element you’re targeting can adjust those styles.
Container queries will be the single biggest change in web styling since CSS3, altering our perspective of what “responsive design” means.
No longer will the viewport and user agent be the only targets we have to create responsive layout and UI styles. With container queries, elements will be able to target their own parents and apply their own styles accordingly. This means that the same element that lives in the sidebar, body, or hero could look completely different based on its available size and dynamics.
@container
in action
In this example, I’m using two cards within a parent with the following markup:
<div class="card-container">
<div class="card">
<figure> ... </figure>
<div>
<div class="meta">
<h2>...</h2>
<span class="time">...</span>
</div>
<div class="notes">
<p class="desc">...</p>
<div class="links">...</div>
</div>
<button>...</button>
</div>
</div>
</div>
Then, I’m setting containment (the contain
property) on the parent on which I’ll be querying the container styles (.card-container
). I’m also setting a relative grid layout on the parent of .card-container
, so its inline-size
will change based on that grid. This is what I’m querying for with @container
:
.card-container {
contain: layout inline-size;
width: 100%;
}
Now, I can query for container styles to adjust styles! This is very similar to how you would set styles using width-based media queries, using max-width
to set styles when an element is smaller than a certain size, and min-width
when it is larger.
/* when the parent container is smaller than 850px,
remove the .links div and decrease the font size on
the episode time marker */
@container (max-width: 850px) {
.links {
display: none;
}
.time {
font-size: 1.25rem;
}
/* ... */
}
/* when the parent container is smaller than 650px,
decrease the .card element's grid gap to 1rem */
@container (max-width: 650px) {
.card {
gap: 1rem;
}
/* ... */
}
Container Queries + Media Queries
One of the best features of container queries is the ability to separate micro layouts from macro layouts. You can style individual elements with container queries, creating nuanced micro layouts, and style entire page layouts with media queries, the macro layout. This creates a new level of control that enables even more responsive interfaces.
Here’s another example that shows the power of using media queries for macro layout (i.e. the calendar going from single-panel to multi-panel), and micro layout (i.e. the date layout/size and event margins/size shifting), to create a beautiful orchestra of queries.
Container Queries + CSS Grid
One of my personal favorite ways to see the impact of container queries is to see how they work within a grid. Take the following example of a plant commerce UI:
No media queries are used on this website at all. Instead, we are only using container queries along with CSS grid to display the shopping card component in different views.
In the product grid, the layout is created with grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
. This creates a layout that tells the cards to take up the available fractional space until they hit 230px
in size, and then to flow to the next row. Check out more grid tricks at 1linelayouts.com.
Then, we have a container query that styles the cards to take on a vertical block layout when they are less than 350px
wide, and shifts to a horizontal inline layout by applying display: flex
(which has an inline flow by default).
@container (min-width: 350px) {
.product-container {
padding: 0.5rem 0 0;
display: flex;
}
/* ... */
}
This means that each card owns its own responsive styling. This yet another example of where you can create a macro layout with the product grid, and a micro layout with the product cards. Pretty cool!
Usage
In order to use @container
, you first need to create a parent element that has containment. In order to do so, you’ll need to set contain: layout inline-size
on the parent. You can use inline-size
since we currently can only apply container queries to the inline axis. This prevents your layout from breaking in the block direction.
Setting contain: layout inline-size
creates a new containing block and new block formatting context, letting the browser separate it from the rest of the layout. Now, we can query!
Limitations
Currently, you can only use the inline axis to set container query styles. In order to make grid children work with @container
, you’ll need to add a wrapper element. While it’s not ideal at the moment, you can still get the effects you want.
Try it out
You can experiment with the @container
property in Chromium today, by navigating to: chrome://flags
in Chrome Canary and turning on the #experimental-container-queries flag.
The post Next Gen CSS: @container appeared first on CSS-Tricks.
You can support CSS-Tricks by being an MVP Supporter.