The new @container property gives us the ability to style elements based on the size of their parent container.
You can think of this as a media query (@media), but instead of relying on the viewport to set styles, these styles can now depend on the target element’s parent container.
Container requests (@container) will be the biggest change in web style since CSS3, changing our understanding of what responsive design means.
The viewport and user agent will no longer be the only targets we need to create responsive UI layout and styles. With container requests, elements will be able to target their parents and apply their own styles accordingly. This means that the same element that is in the sidebar (for example), in the body or in the basebar can look completely different depending on the available size.
@container into action
In this example, I’m using two cards in the parent element with the following markup:
…
I then set the include (property container-type ) on the parent from which I’ll be querying the container (.card-container) styles. I also set a relative grid layout for the .card-container parent, so its inline-size will change based on that grid. Here is what I am requesting with @container:
.card-container {
container-type: inline-size;
width: 100%
}
Now I can use the container query to customize the styles! This is very similar to how you style using media queries based on width , using max-width to style when an element is under 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
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 detailed micro layouts, and you can style entire page layouts with media queries, macro layouts. This creates a new level of control allowing you to create even more responsive interfaces.
Here’s another example demonstrating how media queries can be used for macro layouts (example of a calendar transitioning from one pane to multiple panes) and micro layout (i.e. date layout/size and event/size shift fields) to create a beautiful collection requests.
Container Queries + CSS Grid
One of my favorite ways to see the impact of container queries is to see how they work in grid. Take the following UI example for plant trading:
This site does not use media queries at all. Instead, we only use container queries along with CSS grid to display the shopping card component in different views.
In the product grid, the layout is created using grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));. This creates a layout that tells cards to take up the available fractional space until they reach 230px, and then flow to the next row. Check out more grid tricks at 1linelayouts.com.
We then have a container request that sets up the cards to accept a vertical block layout when they are less than 350px wide, and transitions to a horizontal inline layout by applying display: flex (which has inline flow by default).
@container(min-width: 350px) {
.product-container {
padding: 0.5rem 0 0;
display:flex;
}
/* … */
}
This means that each card has its own responsive style. This is another example of how you can create a macro layout with a product grid and a micro layout with product cards. Pretty awesome!
Application
To use @container, you first need to create a parent element that contains the container. To do this, you need to set the parent element to contain: layout inline-size . You can use inline-size as currently we can only apply container requests to inline.