Container Queries, Before the Browsers Catch Up
Container queries have long been the missing counterpart to media queries: a way to style components based on the size of their parent rather than the viewport. The syntax has been unstable, and browser support has lagged behind the spec’s evolution. But with CSS Container Queries now an official First Public Working Draft, the timing is right for a polyfill that actually lets you write spec-compliant code today.
GoogleChromeLabs has released one that fits that bill. The polyfill takes a straightforward approach: you load it only in browsers that lack native support, write standard container query CSS, and the polyfill handles the rest. No preprocessors, no custom syntax, no proprietary at-rules. It relies on ResizeObserver, MutationObserver, and :is(), which means it runs in all modern browsers — Chrome/Edge 88+, Firefox 78+, and Safari 14+.
How to Use It
Load the polyfill conditionally, when feature detection fails:
// Support Test
const supportsContainerQueries = "container" in document.documentElement.style;
// Conditional Import
if (!supportsContainerQueries) {
import("https://cdn.skypack.dev/container-query-polyfill");
}
The package is available via npm or as a plain <script>, but the conditional-loading pattern keeps it out of the way in browsers that don’t need it. Once loaded, you write CSS the way the spec intends — with one structural caveat: you can’t query the element you’re styling. A container query needs a wrapper to observe.
<div class="weather-wrap">
<dl class="weather">
<div>
<dt>Sunday</dt>
<dd>
<b>26°</b> 7°
</dd>
</div>
<div>
<dt>Monday</dt>
<dd>
<b>34°</b> 11°
</dd>
</div>
<!-- etc -->
</dl>
</div>
Define that wrapper as a containment context:
.weather-wrap {
container: inline-size / weather-wrapper;
/* Shorthand for: */
/* container-type: inline-size; */
/* container-name: weather-wrapper; */
/* For quick testing, do this to get a resize handle on desktop: */
/* resize: both; */
/* overflow: hidden; */
}
Then style the component globally, and layer container-query rules on top:
.weather {
display: flex;
}
@container weather-wrapper size(max-width: 700px) {
.weather {
flex-direction: column;
}
}
That’s the whole pattern. A weather widget, a card, an entire layout module — the same code adapts to its surroundings instead of to the viewport.
What’s Covered, and What Isn’t
An earlier polyfill, cqfill from Jonathan Neal, required a non-standard CSS syntax and a PostCSS build step. This new one abandons that approach entirely, favoring current spec syntax. The docs enumerate a handful of unsupported edge cases, but the mainline use cases — size-based responsive containers — work as expected.
The polyfill itself is compact, coming in around 2.8kb, which makes progressive enhancement a low-cost proposition. Still, polyfilling comes with a practical caveat: because the styles only apply after the JavaScript runs, users can get a brief flash of unstyled content. That’s a mild tradeoff, similar to webfont loading — content remains visible, even if it shifts once the polyfill kicks in. That FOUC goes away entirely once native support appears and the polyfill no longer loads.
The Road Ahead
Container queries and their cousin, CSS scope, both reached First Public Working Draft status in December 2021. That’s a formal step toward standardization, but no guarantee the syntax won’t shift further before browsers commit to shipping. For now, the polyfill gives you the ability to build with the proposed syntax today — and, if the syntax evolves, adjust accordingly before real browser support makes the polyfill unnecessary.



