CSS Container Queries: How to Use Them
Learn how CSS container queries make components respond to their available space, with practical patterns, units, pitfalls, browser support, and examples.
CSS container queries let a component respond to the space available in its containing element, rather than the size of the browser window. For the common width-based case, give an ancestor container-type: inline-size, then put the conditional styles for its descendants inside @container.
This is useful when the same card, panel, or other component can appear in regions with different widths. Keep viewport and device rules in @media; use @container when the component’s containing block should trigger the change. See MDN’s container queries guide and the @container reference.
1. The basic container query
Start with a component’s default layout. Declare an ancestor as a query container, then use a conditional rule to change descendants when the container meets a size condition:
<div class="post">
<article class="card">
<h2>Card title</h2>
<p>Card content</p>
</article>
</div>
.post {
container-type: inline-size;
}
.card h2 {
font-size: 1em;
}
@container (width > 700px) {
.card h2 {
font-size: 2em;
}
}
The declaration goes on an ancestor of the elements styled by the query. The rule styles descendants inside that container; it does not query a sibling or the viewport. An unnamed query uses the nearest eligible ancestor. The 700px threshold is illustrative, not a universal breakpoint: choose a value based on when your component’s content and layout need to change.
2. Choose a container and query axis
Use inline-size for width-driven components
container-type: inline-size enables size queries along the inline axis. In a typical horizontal writing mode, that corresponds to width. It is the usual choice for cards and panels whose layout should respond to available horizontal space, and it avoids imposing block-axis size containment.
For writing-mode-aware CSS, think in terms of the logical inline axis rather than assuming physical width. A condition written with width refers to a physical dimension; use logical dimensions such as inline-size where the supported query syntax and your design call for them.
Use size only when both axes matter
container-type: size allows queries on both the inline and block dimensions. It also applies size containment: the container’s size is computed independently of its contents. If the surrounding layout or explicit sizing does not establish its dimensions, the container can collapse or behave differently from a content-sized box. Use it only when you need both axes and have accounted for that sizing effect.
.chart-frame {
container-type: size;
inline-size: 100%;
block-size: 24rem;
}
@container (height > 320px) {
.chart-frame .chart-legend {
display: block;
}
}
Here the frame has an explicit block size, so its contents do not need to determine that dimension. Adjust the sizing to fit your layout rather than copying the example’s fixed height blindly. For the properties and containment behavior, see MDN’s container-type reference.
3. Name containers when selection needs to be explicit
When a component is nested or a page has multiple independent regions, an unnamed query may select a nearer eligible ancestor than you intended. Give the intended container a name and refer to it in the query:
.post {
container: sidebar / inline-size;
}
@container sidebar (width > 700px) {
.card {
font-size: 1.25rem;
}
}
The container shorthand sets the name and type. You can also set them separately:
.post {
container-name: sidebar;
container-type: inline-size;
}
Use names to document which region drives a component’s styles and to avoid surprises when nested components add their own containers. A named query still targets eligible ancestors, not arbitrary elements elsewhere in the document. MDN documents the shorthand and selection rules in its container queries guide and @container reference.
4. Scale lengths relative to the container
Container query length units let descendant values scale with a query container. The units include cqw (one percent of container width), cqh (one percent of container height), cqi (one percent of inline size), cqb (one percent of block size), and cqmin and cqmax (the smaller and larger of cqi and cqb).
.post {
container-type: inline-size;
}
.card h2 {
font-size: clamp(1.1rem, 4cqi, 2rem);
}
.card {
padding: clamp(1rem, 3cqi, 2rem);
}
The clamp() bounds keep the values within the chosen minimum and maximum while they scale locally. Container-relative units are optional; a fixed size or a query breakpoint can be a better fit for a component’s design. If no eligible container exists for the relevant axis, these units fall back to the corresponding small viewport unit. See MDN’s guide to container query length units.
5. Combine container queries with media queries
These features answer different questions. A media query responds to viewport or device characteristics; a container query responds to the size of a component’s containing block. A page can use both: a container query for a reusable card’s internal layout and a media query for page-level navigation or a device preference.
.post {
container-type: inline-size;
}
.card {
display: block;
}
@container (width > 36rem) {
.card {
display: grid;
grid-template-columns: 10rem 1fr;
gap: 1.5rem;
}
}
@media (prefers-reduced-motion: reduce) {
.card {
scroll-behavior: auto;
}
}
The container threshold should follow the component’s layout needs; the media query above responds to a user preference. Keeping these responsibilities clear makes components reusable without forcing page-level rules to know where every instance appears.
6. Newer query families and browser support
MDN describes @container as widely available across many devices and browser versions since February 2023, while warning that some parts vary in support. Its documentation covers size, style, name-only, scroll-state, and anchored query types. Do not assume every query family, condition, or syntax has the same browser coverage. Check the current compatibility information for the exact feature and browser set you support before relying on it.
Style queries are distinct from size queries. The reviewed MDN guide describes custom-property style queries separately and reports narrower support; it also says ordinary CSS declaration/property checks through style() are not supported in any browser on that guide page. That support information can change, so verify the current MDN guide to size and style queries and compatibility data when adopting them. The established size-query pattern shown above is the practical starting point.
7. Troubleshoot common problems
| Symptom | Likely cause | What to check |
|---|---|---|
| The query never matches. | No eligible query container is an ancestor of the styled element, or the container is not the one you expected. | Put container-type on an ancestor, inspect nested containers, and add a container-name to make selection explicit. |
| The layout changes at an unexpected size. | An unnamed query is using the nearest eligible ancestor, or the chosen threshold does not fit the component’s actual available space. | Check the ancestor chain and container’s measured size; name the intended container and tune the threshold to the content. |
| The container collapses or loses content-based sizing. | container-type: size imposes size containment, so its dimensions are not derived from its children. |
Use inline-size if only the inline axis is needed, or establish both dimensions through layout context or explicit constraints. |
| Container units scale against the viewport. | No eligible container exists for that unit’s axis. | Declare a suitable size query container on an ancestor, and confirm it is eligible for the axis used. |
| A new query syntax works in one browser but not another. | Support varies across query families and syntax. | Check compatibility for the specific feature, provide a sensible default style outside the query, and add progressive enhancement where needed. |
| The query styles the wrong nested component. | A nearer eligible container or an overly broad selector changes the scope you expected. | Name the intended container and scope selectors to the component descendants that should change. |
8. Performance, reliability, and maintenance
Container queries let a component adapt locally, which can reduce the need for placement-specific variants. Keep the queried container close to the region whose space should govern the component, use the narrowest query type that meets the design, and avoid adding size containment without a sizing plan. These choices make the layout behavior easier to reason about.
There is no universal breakpoint or performance figure in the source material for this guide. Validate the component in the layouts and browsers you support, especially when using newer query families. Leave a usable default outside conditional rules so the component remains understandable when a particular enhancement is unavailable.
9. Or skip the browser setup
If your goal is to capture what a page looks like rather than implement a responsive component, ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF, and its parameters use names familiar from other screenshot APIs. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Before capture, ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and whether the shot was billed. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month, with no card.
10. FAQ
Can a container query style the container itself?
The query condition is evaluated against an eligible ancestor container, and the conditional styles apply to descendants inside it. Put the rule on the elements within the container that need to change.
Do I need a container name for every query?
No. An unnamed query is enough when the nearest eligible ancestor is the intended one. Add a name when nesting or multiple regions could make that choice unclear.
Should every responsive component use container queries?
No. Use them when the component should respond to its own available space. Use media queries for viewport or device conditions, and combine both when the page and component have separate responsive needs.
Are style and scroll-state queries interchangeable with size queries?
No. They query different kinds of conditions, and their support can differ. Check current compatibility for the specific query type and syntax before using it.


