CSS Responsive Layout Media Queries Container Queries
Definisi
Responsive layout adalah pendekatan CSS untuk membuat UI menyesuaikan ruang yang tersedia tanpa mengorbankan keterbacaan, konsistensi spacing, dan fungsi komponen.
Tiga alat yang paling sering dipakai adalah:
- media queries: mengubah style berdasarkan kondisi viewport atau media feature tertentu
- fluid sizing: membuat ukuran mengikuti ruang dengan nilai fleksibel seperti
%,vw,rem,clamp(),min(), danmax() - container queries: mengubah style berdasarkan ukuran container tempat komponen dirender, bukan ukuran viewport global
Kenapa penting
Banyak layout responsif gagal bukan karena CSS-nya salah, tetapi karena strategi responsifnya terlalu bergantung pada lebar layar.
Gejala yang sering muncul:
- komponen terlihat bagus di desktop, tetapi pecah saat dipindah ke sidebar atau panel kecil
- breakpoint terlalu banyak dan sulit dirawat
- ukuran teks, kartu, dan grid berubah terlalu agresif di beberapa lebar layar
- komponen tidak punya perilaku yang stabil saat dipakai ulang di konteks berbeda
Kalau pendekatannya tepat, komponen jadi lebih tahan terhadap perubahan container, bukan cuma perubahan viewport.
Tiga lapis strategi responsif
Pendekatan yang paling aman biasanya bertingkat:
- Mulai dari fluid sizing untuk ukuran dasar yang bisa mengalir
- Tambah media queries saat layout perlu berubah pada ambang tertentu
- Gunakan container queries saat komponen harus merespons ruang tempat ia berada, bukan layar secara keseluruhan
Media queries
Media queries dipakai untuk mengubah style ketika kondisi tertentu terpenuhi.
Contoh paling umum adalah breakpoint berdasarkan lebar viewport:
.card-grid {
display: grid;
gap: 1rem;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.card-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (min-width: 1024px) {
.card-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}Kapan pakai breakpoint
Pakai breakpoint saat ada perubahan struktur yang sulit dicapai hanya dengan ukuran fluid.
Contoh yang tepat:
- navigasi berubah dari drawer ke horizontal bar
- card list berubah dari 1 kolom ke beberapa kolom
- sidebar pindah dari bawah ke samping
- urutan elemen perlu diubah pada ukuran tertentu
- whitespace dan alignment perlu disesuaikan untuk ruang yang jauh lebih besar atau kecil
Kapan tidak perlu breakpoint
Jangan buru-buru menambah breakpoint kalau masalahnya cukup diselesaikan dengan nilai fluid.
Misalnya:
- teks terlalu rapat → atur
line-height,max-width, atau skala font - kartu terlalu lebar → batasi dengan
max-widthatauminmax() - gambar terlalu besar → pakai
width: 100%danheight: auto - spacing terasa kaku → gunakan
clamp()
Prinsip breakpoint yang sehat
- gunakan breakpoint berdasarkan kebutuhan konten, bukan model device
- mulai dari mobile-first: style dasar untuk layar kecil, lalu tambah aturan dengan
min-width - minimalkan jumlah breakpoint
- jadikan breakpoint sebagai momen perubahan layout, bukan tambalan untuk semua masalah
Fluid sizing
Fluid sizing membuat ukuran berubah secara bertahap mengikuti ruang yang tersedia.
Ini biasanya lebih stabil daripada langsung meloncat di breakpoint.
Nilai yang umum dipakai
%untuk lebar relatif terhadap parentremuntuk skala yang konsisten dengan typographyvwuntuk ukuran yang mengikuti viewportminmax()untuk grid track yang fleksibelclamp()untuk batas minimum, ideal, dan maksimummax-widthdanmin-widthuntuk menjaga batas aman
Contoh fluid typography
.article {
max-width: 70ch;
padding-inline: clamp(1rem, 2vw, 2rem);
font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
line-height: 1.6;
}Di sini:
max-width: 70chmenjaga panjang baris tetap nyaman dibacaclamp()membuat padding dan font size berubah halus- pembaca tidak mengalami perubahan yang terlalu mendadak
Contoh fluid grid
.product-list {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}Pola ini sangat berguna karena grid otomatis menyesuaikan jumlah kolom sesuai ruang yang tersedia.
Kenapa fluid sizing penting
Kalau semua ukuran dikunci pada breakpoint, UI cenderung terasa patah-patah.
Fluid sizing membantu:
- mengurangi jumlah breakpoint
- menjaga transisi layout tetap halus
- membuat komponen lebih tahan terhadap variasi kontainer
- menghindari ukuran ekstrem di layar sangat lebar atau sangat sempit
Container queries
Container queries dipakai saat style komponen harus bergantung pada ukuran container tempat ia berada.
Ini penting karena komponen yang sama bisa tampil di:
- main content area
- sidebar
- modal
- panel kecil di dashboard
- halaman penuh
Kalau hanya mengandalkan viewport, komponen bisa salah membaca konteks.
Cara kerja singkat
- parent dijadikan container
- komponen di dalamnya menanyakan ukuran container tersebut
- style berubah jika ukuran container melewati ambang tertentu
.card-shell {
container-type: inline-size;
}
.card {
display: grid;
gap: 0.75rem;
grid-template-columns: 1fr;
}
@container (min-width: 30rem) {
.card {
grid-template-columns: 160px 1fr;
align-items: start;
}
}Kapan container queries lebih tepat daripada media queries
Gunakan container queries kalau:
- komponen reusable dipakai di banyak tempat dengan lebar berbeda
- perubahan layout seharusnya mengikuti ruang container, bukan ukuran layar
- komponen bisa dipindah ke sidebar atau panel sempit tanpa ingin ikut aturan viewport utama
- desain sistem butuh komponen yang mandiri
Kapan media queries tetap dibutuhkan
Container queries bukan pengganti total media queries.
Media queries tetap cocok untuk:
- perubahan global yang menyangkut halaman penuh
- preferensi user atau media feature tertentu
- struktur aplikasi yang memang berubah mengikuti viewport
- aturan dasar yang berlaku di seluruh halaman
Pola kombinasi yang sehat
Pola yang sering paling stabil:
- media queries untuk perubahan layout global
- container queries untuk perilaku komponen
- fluid sizing untuk jembatan di antara keduanya
Cara memilih strategi responsif
Pertanyaan paling berguna bukan “berapa breakpoint yang harus dipakai?”, tapi “yang berubah itu halaman, komponen, atau ukurannya?”
Pakai fluid sizing jika
- perubahan yang dibutuhkan bersifat bertahap
- ukuran teks, spacing, atau card butuh skala lembut
- kamu ingin mengurangi lompatan visual
- komponen belum memerlukan perubahan struktur besar
Pakai media queries jika
- layout halaman perlu berubah pada ambang lebar tertentu
- ada breakpoint desain yang jelas dari tim desain
- struktur navigasi atau sidebar benar-benar berubah
- state layout tergantung viewport, bukan container
Pakai container queries jika
- komponen harus responsif saat dipindah konteks
- ukuran viewport bukan sinyal yang cukup
- kamu membangun design system atau komponen reusable
- satu komponen harus cocok di area lebar maupun area sempit
Jebakan umum
1. Terlalu banyak breakpoint
Terlalu banyak breakpoint biasanya tanda bahwa layout dasar belum fluid.
Akibatnya:
- CSS sulit dirawat
- perubahan kecil memicu banyak override
- style cepat saling bertabrakan
Kalau kamu merasa perlu breakpoint tiap 100px, biasanya ada masalah pada struktur atau sizing dasar.
2. Mengandalkan viewport untuk semua komponen
Ini jebakan paling umum.
Komponen yang bagus di desktop belum tentu bagus saat dipasang di area yang sempit. Kalau komponen selalu membaca viewport, ia akan salah konteks saat dipindah ke panel kecil.
3. Ukuran elemen terlalu keras
Contoh yang sering bermasalah:
- width tetap untuk card
- gambar tanpa constraint
- grid column yang tidak boleh menyusut
- teks tanpa batas panjang baris
Solusinya biasanya bukan breakpoint tambahan, tetapi constraint yang lebih sehat.
4. Lupa mengatur min-width: 0 pada flex item
Ini jebakan klasik.
Dalam layout flex, item sering tidak mau menyusut karena ukuran intrinsik kontennya.
.row {
display: flex;
}
.row__content {
min-width: 0;
}Tanpa ini, teks panjang bisa mendorong layout meluber.
5. Menggunakan vw tanpa batas
vw berguna, tetapi kalau dipakai mentah-mentah, ukuran bisa terlalu ekstrem di layar besar atau terlalu kecil di layar sempit.
Lebih aman pakai clamp() untuk memberi batas minimum dan maksimum.
6. Mengatur layout sebelum menetapkan constraint konten
Sering kali masalah tampak seperti masalah grid atau breakpoint, padahal akar masalahnya ada di konten:
- heading terlalu panjang
- gambar tidak proporsional
- teks tidak bisa wrap
- component child tidak fleksibel
Jangan langsung menambah breakpoint kalau konten dasarnya belum dibatasi dengan benar.
7. Mengira container queries otomatis menyelesaikan semuanya
Container queries kuat, tetapi tetap butuh struktur parent yang benar.
Kalau container belum disiapkan dengan benar, atau ukuran internal tidak fleksibel, hasilnya tetap bisa kacau.
Pola implementasi yang praktis
1. Mulai dari komponen yang fluid
.card {
display: grid;
gap: 1rem;
max-width: 100%;
padding: clamp(1rem, 2vw, 1.5rem);
}
.card__title {
max-width: 20ch;
}2. Tambah breakpoint hanya saat struktur perlu berubah
@media (min-width: 64rem) {
.layout {
display: grid;
grid-template-columns: 18rem minmax(0, 1fr);
gap: 1.5rem;
}
}3. Pindahkan responsif komponen ke container query
.panel {
container-type: inline-size;
}
.panel__content {
display: grid;
grid-template-columns: 1fr;
}
@container (min-width: 36rem) {
.panel__content {
grid-template-columns: 12rem minmax(0, 1fr);
}
}Catatan implementasi
- Mulai dari fluid sizing sebelum menambah breakpoint.
- Pakai media queries untuk perubahan layout global.
- Pakai container queries untuk komponen yang harus responsif di banyak konteks.
- Gunakan
clamp()untuk ukuran yang perlu tumbuh dan menyusut dengan batas aman. - Gunakan
minmax(0, 1fr)danmin-width: 0untuk mencegah overflow yang sering muncul di grid atau flex. - Jangan jadikan breakpoint sebagai alat untuk menambal layout yang belum sehat.
- Ukur dari konten dan container, bukan dari nama device.
- Kalau komponen reusable terasa “cuma cocok di homepage”, biasanya ia terlalu bergantung pada viewport.
Istilah
- Breakpoint: titik lebar tertentu saat style berubah.
- Fluid sizing: ukuran yang mengikuti ruang secara bertahap.
- Viewport: area tampilan browser atau layar yang dipakai untuk media query.
- Container query: query CSS yang bergantung pada ukuran container, bukan viewport.
clamp(): fungsi untuk memberi nilai minimum, ideal, dan maksimum.minmax(): fungsi grid untuk batas minimum dan maksimum track.- Reusable component: komponen yang tetap bekerja di berbagai konteks layout.
Referensi terkait
- Box Model: dasar perhitungan ruang elemen.
- Flexbox vs Grid: memilih sistem layout yang tepat sebelum membuat responsif.
- Display, Overflow, dan Containment Sederhana: saat responsif terganggu oleh overflow atau aliran layout.