Container Query Fallback Strategy for Older Browsers
Ship CSS container queries safely with @supports detection, media query fallbacks, and progressive enhancement so legacy browsers still get a working — if simpler — experience.
Detailed Explanation
Shipping Container Queries Without Breaking Anything
Container queries have shipped in all evergreen browsers since 2023. Even so, you may have users on locked-down enterprise browsers, embedded WebViews, or older OS versions. Here's how to deploy without regressions.
Step 1: Default to a Mobile-First Base
Write your component's CSS so the un-enhanced state works at narrow widths. Older browsers will simply receive this state at every host size.
.card {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
Step 2: Wrap Enhancements in @supports
@supports (container-type: inline-size) {
.card-host {
container-type: inline-size;
container-name: card;
}
@container card (min-width: 400px) {
.card {
flex-direction: row;
align-items: flex-start;
}
.card img {
width: 40%;
max-width: 200px;
}
}
}
Browsers that don't understand container-type skip the entire block, keeping the simple base layout.
Step 3: Optional Media Query Fallback
If you want the horizontal layout on wide viewports even in legacy browsers (knowing the card might be in a narrow slot), add a media query outside the @supports block:
@media (min-width: 768px) {
.card {
flex-direction: row;
align-items: flex-start;
}
.card img { width: 40%; max-width: 200px; }
}
/* And undo it for modern browsers so the container query takes over */
@supports (container-type: inline-size) {
@media (min-width: 768px) {
.card { flex-direction: column; }
.card img { width: 100%; max-width: none; }
}
}
This is more complex but ensures legacy users get a desktop layout on desktop screens, while modern users get container-aware behavior everywhere.
Step 4: JS Detection (When Necessary)
const supportsCQ = CSS.supports('container-type', 'inline-size');
document.documentElement.dataset.cq = supportsCQ ? 'yes' : 'no';
Then in CSS:
[data-cq="no"] .card { /* legacy-specific tweaks */ }
Use this only when CSS-only fallbacks aren't enough.
Polyfill Considerations
The Chrome Labs container query polyfill exists but adds JS overhead and doesn't cover every edge case. For most projects, a graceful base + @supports is enough. Reserve polyfilling for projects where legacy browser support is contractually required.
Testing Checklist
- Component looks correct without any container query support (disable in DevTools).
- Component progressively enhances on modern browsers.
- No layout shift between base and enhanced states.
-
@supportsblock is the only place that declarescontainer-type.
Use Case
Use this strategy when shipping container queries to production sites that must support enterprise browsers, embedded WebViews, or older OS versions. Combine @supports with a mobile-first base for safe progressive enhancement.