CSS Container Queries: Masa Depan Desain Responsif (2026)
Bertahun-tahun developer wishlist "responsive berdasarkan parent container, bukan viewport". Tahun 2026, akhirnya: container queries stable di semua major browser. Tapi banyak developer masih default ke media query untuk semua, padahal container query lebih cocok untuk many situations.
Artikel ini bahas container queries dari basic sampai advanced pattern, plus kapan pakai yang mana antara container query vs media query.
Masalah Yang Container Query Solve
Selama ini, responsive design pakai media query yang base on viewport size. Problem: component reusable yang dipake di multiple location, ukurannya beda-beda walau viewport sama.
Contoh: card component dipake di:
- Sidebar (300px wide)
- Main content (700px wide)
- Modal (500px wide)
Media query ngga help karena viewport sama untuk ketiga case. Solusi sebelum container query: pakai prop atau JavaScript untuk handle ini, ngga clean.
Container query: card adapts berdasarkan ukuran parent-nya, bukan viewport. Layout yang berbeda untuk setiap konteks, dari CSS murni.
Syntax Basic
Setup container:
.parent {
container-type: inline-size;
/* atau "size" untuk both width + height */
container-name: card-container; /* optional, untuk multiple container */
}
Style berdasarkan size container:
@container (min-width: 400px) {
.card {
display: grid;
grid-template-columns: auto 1fr;
gap: 1rem;
}
}
@container (min-width: 700px) {
.card {
grid-template-columns: 200px 1fr 200px;
}
}
/* Dengan named container */
@container card-container (min-width: 400px) {
.card { padding: 2rem; }
}
Card yang sama, di parent berbeda, render layout berbeda. Tanpa JavaScript.
Pattern Praktis
1. Card Component Adaptive
<div class="card-wrap">
<article class="card">
<img src="..." alt="...">
<div class="content">
<h3>Title</h3>
<p>Description...</p>
</div>
</article>
</div>
.card-wrap {
container-type: inline-size;
}
.card {
display: grid;
}
/* Compact: stacked vertically */
.card .content { padding: 1rem; }
/* Wide: horizontal layout */
@container (min-width: 400px) {
.card {
grid-template-columns: 200px 1fr;
}
}
@container (min-width: 700px) {
.card {
grid-template-columns: 300px 1fr;
}
.card .content { padding: 2rem; font-size: 1.1rem; }
}
2. Sidebar Widget
Widget yang adapt: kalau sidebar tetap, layout vertical. Kalau sidebar collapse jadi top bar, layout horizontal.
aside {
container-type: inline-size;
}
.widget {
display: flex;
flex-direction: column;
}
@container (min-width: 600px) {
.widget {
flex-direction: row;
justify-content: space-between;
}
}
3. Form Field Layout
Form yang otomatis adjust label position berdasarkan available width:
.form {
container-type: inline-size;
}
.field {
display: grid;
gap: 0.5rem;
}
@container (min-width: 500px) {
.field {
grid-template-columns: 200px 1fr;
align-items: center;
}
}
Form di modal sempit: label di atas. Form di halaman lebar: label di samping.
4. Navigation Menu
nav {
container-type: inline-size;
}
.menu {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
@container (min-width: 600px) {
.menu {
flex-direction: row;
gap: 2rem;
}
}
@container (max-width: 599px) {
.menu-toggle {
display: block; /* Show hamburger */
}
.menu {
display: none;
}
.menu.open {
display: flex;
}
}
Container Query Units
Selain container query, container query juga kasih units baru:
cqw: 1% width containercqh: 1% height containercqi: 1% inline size containercqb: 1% block size containercqmin: minimum dari cqi/cqbcqmax: maximum dari cqi/cqb
Use case: text yang scale based on container, bukan viewport:
.parent {
container-type: inline-size;
}
.title {
font-size: clamp(1.5rem, 5cqw, 3rem);
/* Scale berdasarkan container width, dengan min/max */
}
Title 5% lebar container, dengan minimum 1.5rem dan maximum 3rem.
Container Query vs Media Query: Kapan Pakai Yang Mana
Pakai Media Query Untuk:
- Layout level page: full page restructure based on device size
- Print stylesheet:
@media print - Reduced motion:
@media (prefers-reduced-motion: reduce) - Color scheme:
@media (prefers-color-scheme: dark) - Hover capability:
@media (hover: hover) - Device pixel ratio: untuk retina image swap
Pakai Container Query Untuk:
- Reusable component: card, widget, form, navigation
- Component yang multi-context: dipake di sidebar dan main content
- Library / design system component: distribute component yang adapt without consumer config
- Layout component-level: header internal, footer adapt
Performance Considerations
1. Browser Cost
Container queries trigger layout recalculation saat container size berubah. Untuk most case, cost minimal. Tapi excessive container query di nested level deep bisa impact performance.
Best practice: limit container hierarchy ke 2-3 level. Setiap component butuh container biasanya cuma 1 level.
2. Layout Containment
container-type: inline-size implicitly apply contain: layout style inline-size. Element jadi containing block. Ada side effect:
- Position: absolute pada anak akan position relative ke container, bukan ke ancestor lain
- Element ngga bisa "leak" out dari container untuk layout
Most case ini desirable, tapi kalau lo punya komponen yang relies on positioning ke ancestor lain, test carefully.
Browser Support 2026
- Chrome / Edge: full support sejak v105 (2022)
- Safari: full support sejak 16.0 (2022)
- Firefox: full support sejak 110 (2023)
- Mobile: all modern mobile browser support
Coverage 95%+ di 2026. Untuk older browser, fallback ke media query atau JavaScript.
Pitfalls Common
1. Lupa Set container-type
Most common mistake. Lo write @container rule tapi lupa set parent jadi container. Rule ngga apply.
/* Salah - parent ngga jadi container */
@container (min-width: 400px) {
.card { ... }
}
/* Benar */
.parent {
container-type: inline-size; /* WAJIB */
}
@container (min-width: 400px) {
.card { ... }
}
2. Apply ke Self Element
Container query ngga bisa style element yang itself container. Element jadi container, lo style descendantnya.
/* Salah - .self adalah container, di-apply ke dirinya */
.self {
container-type: inline-size;
}
@container (min-width: 400px) {
.self { padding: 2rem; } /* NGGA WORK */
}
/* Benar - container styling diluar @container, descendant didalam */
.self {
container-type: inline-size;
padding: 1rem;
}
@container (min-width: 400px) {
.self > .child { padding: 2rem; } /* WORK */
}
3. Width 0 Issue
Element dengan display: contents atau ngga ada width meaningful, container ngga work as expected. Container butuh width yang resolvable.
4. Naming Collision
Multiple ancestor jadi container, query bisa match ancestor yang ngga lo expect. Pakai container-name untuk specificity.
Penutup
Container queries akhirnya solve masalah long-standing di responsive design: component yang adapt ke konteks, bukan ke viewport. Browser support sekarang stable, syntax mature, performance acceptable.
Di 2026, kalau lo build component-based design system, container queries should be default tool. Pakai media query untuk page-level layout, container query untuk component-level adaptation.
Yang ngga perlu: rewrite seluruh stylesheet existing untuk pakai container query. Apply gradual untuk component baru atau component yang current pattern-nya awkward dengan media query.
Plus: explore container query units (cqw, cqh, dll). Mereka unlock pattern fluid typography dan spacing yang sebelumnya butuh JavaScript ResizeObserver.