Container queries are often considered a modern approach to responsive web design where traditional media queries have long been the gold standard — the reason being that we can create layouts made with elements that respond to, say, the width of their containers rather than the width of the viewport.
.parent { container-name: hero-banner; container-type: inline-size; /* or container: hero-banner / inline-size; */}}.child { display: flex; flex-direction: column;}/* When the container is greater than 60 characters... */@container hero-banner (width > 60ch) { /* Change the flex direction of the .child element. */ .child { flex-direction: row; }}
Why care about CSS Container Queries?1. When using a container query, we give elements the ability to change based on their container’s size, not the viewport.
2. They allow us to define all of the styles for a particular element in a more predictable way.
3. They are more reusable than media queries in that they behave the same no matter where they are used. So, if you were to create a component that includes a container query, you could easily drop it into another project and it will still behave in the same predictable fashion.
4. They introduce new types of CSS length units that can be used to size elements by their container’s size.
Table of Contents * Registering Elements as Containers
* Querying a Container
* Container Queries Properties & Values
* Specification
* Browser Support
* Demos!
* Articles & Tutorials
Registering Elements as Containers
.cards { container-name: card-grid; container-type: inline-size; /* Shorthand */ container: card-grid / inline-size;}
This example registers a new container named card-grid that can be queried by its inline-size, which is a fancy way of saying its “width” when we’re working in a horizontal writing mode. It’s a logical property. Otherwise, “inline” would refer to the container’s “height” in a vertical writing mode.
**container-name** property is used to register an element as a container that applies styles to other elements based on the container’s size and styles.**container-type** property is used to register an element as a container that can apply styles to other elements when it meets certain conditions.container property is a shorthand that combines the container-name and container-type properties into a single declaration.
Some Possible Gotchas The container-name property is optional.* An unnamed container will match any container query that does not target a specific container, meaning it could match multiple conditions.container-type property is required if we want to query a container by its size or inline-size. The size refers to the container’s inline or block direction, whichever is larger. The inline-size refers to the container’s width in the default horizontal writing mode.container-type property’s default value is normal. And by “normal” that means all elements are containers by default, only they are called Style Containers and can only be queried by their applied styles. For example, we can query a container’s background-color value and apply styles to other elements when the value is a certain color value.background-color when it is a certain size — but we can change the background-color of any element inside the container. “You cannot style what you query” is a way to think about it.@container my-container (width > 60ch) { article { flex-direction: row; }}**@container** at-rule property informs the browser that we are working with a container query rather than, say, a media query (i.e., @media).**my-container** part in there refers to the container’s name, as declared in the container’s container-name property.article element represents an item in the container, whether it’s a direct child of the container or a further ancestor. Either way, the element must be in the container and it will get styles applied to it when the queried condition is matched.
Some Possible Gotchas The container’s name is optional. If we leave it out, then any* registered container would match when the conditions are met.width can be queried with when the container-type property is set to either size or inline-size. That’s because size can query the element’s width or height; meanwhile, inline-size can only refer to the width.width (i.e., inline-size), there’s an element’s aspect-ratio, block-size (i.e., height), and orientation (e.g. portrait and landscape).>) and “less than” (<), but there is also “equals” (=) and combinations of the three, such as “more than or equal to” (>=) and “less than or equal to” (<=).and, or, and not.
Container Queries Properties & Values Container Queries Properties & Valuescontainer-name
container-name: none | <custom-ident>+;
Value Descriptions * none: The element does not have a container name. This is true by default, so you will likely never use this value, as its purpose is purely to set the property’s default behavior.<custom-ident>: This is the name of the container, which can be anything, except for words that are reserved for other functions, including default, none, at, no, and or. Note that the names are not wrapped in quotes.
Open in Almanac Initial value:* nonenone or an ordered list of identifierscontainer-type
container-type: normal | size | inline-size;
Value Descriptions * normal: This indicates that the element is a container that can be queried by its styles rather than size. All elements are technically containers by default, so we don’t even need to explicitly assign a container-type to define a style container.size: This is if we want to query a container by its size, whether we’re talking about the inline or block direction.inline-size: This allows us to query a container by its inline size, which is equivalent to width in a standard horizontal writing mode. This is perhaps the most commonly used value, as we can establish responsive designs based on element size rather than the size of the viewport as we would normally do with media queries.
Open in Almanac Initial value:* normalcontainer
container: <'container-name'> [ / <'container-type'> ]?
Value Definitons If <'container-type'> is omitted, it is reset to its initial value of normalwhich defines a style container instead of a size container. In other words, all elements are style containers by default, unless we explicitly set the container-type property value to either size or inline-size which allows us to query a container’s size dimensions.Open in Almanac Initial value: none / normal
* Applies to: All elements
* Inherited: No
* Percentages: N/A
* Computed value: As specified
* Canonical order: Per grammar
* Animation:* Not animatable
Container Length Units Container Width & Height Units
| Unit | Name | Equivalent to… |
| --- | --- | --- |
| cqw | Container query width | 1% of the queried container’s width |
| cqh | Container query height | 1% of the queried container’s height |
Container Logical Directions
| Unit | Name | Equivalent to… |
| --- | --- | --- |
| cqi | Container query inline size | 1% of the queried container’s inline size, which is its width in a horizontal writing mode. |
| cqb | Container query block size | 1% of the queried container’s inline size, which is its height in a horizontal writing mode. |
Container Minimum & Maximum Lengths
| Unit | Name | Equivalent to… |
| --- | --- | --- |
| cqmin | Container query minimum size | The value of cqi or cqb, whichever is smaller. |
| cqmax | Container query maximum size | The value of cqi or cqb, whichever is larger. |
Container Style Queries Container Style Queries is another piece of the CSS Container Queries puzzle. Instead of querying a container by its size or inline-size, we can query a container’s CSS styles. And when the container’s styles meet the queried condition, we can apply styles to other elements. This is the sort of “conditional” styling we’ve wanted on the web for a long time: If these styles match over here, then apply these other styles over there.
CSS Container Style Queries are only available as an experimental feature in modern web browsers at the time of this writing, and even then, style queries are only capable of evaluating CSS custom properties (i.e., variables).
Browser Support The feature is still considered experimental at the time of this writing and is not supported by any browser, unless enabled through feature flags.
This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.
Desktop
| Chrome | Firefox | IE | Edge | Safari | | --- | --- | --- | --- | --- | | 128 | No | No | 125 | TP |
Mobile / Tablet
| Android Chrome | Android Firefox | Android | iOS Safari | | --- | --- | --- | --- | | 125 | No | 125 | No |
Registering a Style Container
article { container-name: card;}
That’s really it! Actually, we don’t even need the container-name property unless we need to target it specifically. Otherwise, we can skip registering a container altogether.
And if you’re wondering why there’s no container-type declaration, that’s because all elements are already considered containers. It’s a lot like how all elements are position: relative by default; there’s no need to declare it. The only reason we would declare a container-type is if we want a CSS Container Size Query instead of a CSS Container Style Query.
So, really, there is no need to register a container style query because all elements are already style containers right out of the box! The only reason we’d declare container-name, then, is simply to help select a specific container by name when writing a style query.
Using a Style Container Query
@container style(--bg-color: #000) { p { color: #fff; }}
In this example, we’re querying any matching container (because all elements are style containers by default).
Notice how the syntax it’s a lot like a traditional media query? The biggest difference is that we are writing @container instead of @media. The other difference is that we’re calling a style() function that holds the matching style condition. This way, a style query is differentiated from a size query, although there is no corresponding size() function.
In this instance, we’re checking if a certain custom property named --bg-color is set to black (#000). If the variable’s value matches that condition, then we’re setting paragraph (p) text color to white (#fff).
Custom Properties & Variables
.card-wrapper { --bg-color: #000;}.card { @container style(--bg-color: #000) { /* Custom CSS */ }}
Nesting Style Queries
@container style(--featured: true) { article { grid-column: 1 / -1; } @container style(--theme: dark) { article { --bg-color: #000; --text: #fff; } }}
SpecificationCSS Container Queries are defined in the CSS Containment Module Level 3 specification, which is currently in Editor’s Draft status at the time of this writing.
Browser SupportBrowser support for CSS Container Size Queries is great. It’s just style queries that are lacking support at the time of this writing.
This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.
Desktop
| Chrome | Firefox | IE | Edge | Safari | | --- | --- | --- | --- | --- | | 106 | 110 | No | 106 | 16.0 |
Mobile / Tablet
| Android Chrome | Android Firefox | Android | iOS Safari | | --- | --- | --- | --- | | 125 | 126 | 125 | 16.0 |
Demos! Card Component In this example, a “card” component changes its layout based on the amount of available space in its container.
CodePen Embed Fallback Call to Action Panel This example is a lot like those little panels for signing up for an email newsletter. Notice how the layout changes three times according to how much available space is in the container. This is what makes CSS Container Queries so powerful: you can quite literally drop this panel into any project and the layout will respond as it should, as it’s based on the space it is in rather than the size of the browser’s viewport.
CodePen Embed Fallback Stepper Component This component displays a series of “steps” much like a timeline. In wider containers, the stepper displays steps horizontally. But if the container becomes small enough, the stepper shifts things around so that the steps are vertically stacked.
CodePen Embed Fallback Icon Button Sometimes we like to decorate buttons with an icon to accentuate the button’s label with a little more meaning and context. And sometimes we don’t know just how wide that button will be in any given context, which makes it tough to know when exactly to hide the icon or re-arrange the button’s styles when space becomes limited. In this example, an icon is displayed to the right edge of the button as long as there’s room to fit it beside the button label. If room runs out, the button becomes a square tile that stacks the icons above the label. Notice how the border-radius is set in container query units, 4cqi, which is equal to 4% of the container’s inline-size (i.e. width) and results in rounder edges as the button grows in size.
CodePen Embed Fallback Pagination Pagination is a great example of a component that benefits from CSS Container Queries because, depending on the amount of space we have, we can choose to display links to individual pages, or hide them in favor of only two buttons, one to paginate to older content and one to paginate to newer content.
CodePen Embed FallbackArticles & Tutorials General Information Article on Oct 4, 2022 Say Hello to CSS Container Queries container-queries Robin Rendle Article on Dec 16, 2019 The Origin Story of Container Queries container-queries Robin Rendle Article on Jun 11, 2021 A Cornucopia of Container Queries container-queries Geoff Graham Article on Apr 6, 2017 Container Query Discussion container-queries Chris Coyier Article on Jul 1, 2015 Container Queries: Once More Unto the Breach container-queries Chris Coyier Article on Aug 29, 2022 Next Gen CSS: @container container-queries Una Kravets Article on May 17, 2021 251: Container Queries are the Future container-queries Geoff Graham Article on Oct 9, 2019 Let’s Not Forget About Container Queries container-queries Chris Coyier Article on Dec 2, 2020 Minimal Takes on Faking Container Queries container-queries Chris Coyier Article on Nov 12, 2020 The Raven Technique: One Step Closer to Container Queries container-queries Mathias Hülsbusch Container Size Query Tutorials Article on Jun 15, 2021 Media Queries in Times of @container container-queries Chris Coyier Article on Sep 21, 2022 Can We Create a “Resize Hack” With Container Queries? container-queries Jhey Tompkins Article on Dec 13, 2022 A Few Times Container Size Queries Would Have Helped Me Out container-queries Dan Christofi Article on Jan 19, 2022 A New Container Query Polyfill That Just Works container-queries Chris Coyier Article on Jun 21, 2021 256: When to use @container queries container-queries Geoff Graham Article on Sep 1, 2022 iShadeed’s Container Queries Lab container-queries Geoff Graham Article on Dec 2, 2020 Minimal Takes on Faking Container Queries container-queries Chris Coyier Article on May 4, 2020 Playing With (Fake) Container Queries With watched-box & resizeasaurus container-queries Chris Coyier Container Style Queries Article on Nov 7, 2022 Early Days of Container Style Queries container-queries Geoff Graham Article on May 22, 2024 Digging Deeper Into Container Style Queries container-queries Geoff Graham Almanac References Almanac on May 22, 2024 container .element { container: cards-grid / inline-size; } container-queries Geoff Graham Almanac on May 22, 2024 container-name .element { container-name: cards-grid; } container-queries Geoff Graham Almanac on May 22, 2024 container-type .element { container-type: inline-size; } container-queries Geoff Graham Related Guides Article on May 1, 2024 A Complete Guide to CSS Media Queries container-queries Andrés Galante Article on May 23, 2024 A Complete Guide to Custom Properties container-queries Chris Coyier
CSS Container Queries originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.