Responsive Design Tanpa Membuat CSS Berantakan
Membuat komponen yang mampu beradaptasi di berbagai lebar dan cara input tanpa menumpuk breakpoint berdasarkan nama perangkat.
Responsive design bukan membuat versi ponsel, tablet, dan desktop secara terpisah. Tujuannya adalah memberi layout yang tetap dapat digunakan pada rentang ruang, ukuran teks, orientasi, dan metode input yang berubah. Mulailah dari batas konten, lalu tambahkan breakpoint hanya ketika hubungan antarelemen perlu berubah.
- Normal flow dan satu kolom sebagai fondasi.
- Ukuran fleksibel dengan batas minimum dan maksimum.
- Grid intrinsik untuk daftar kartu.
- Media query berdasarkan titik rusaknya konten.
- Container query untuk komponen yang dipakai di wadah berbeda.
Mulai dengan viewport yang benar
<meta name="viewport" content="width=device-width, initial-scale=1">
Meta viewport meminta browser mobile mencocokkan lebar layout dengan lebar perangkat. Jangan menambahkan maximum-scale=1 atau user-scalable=no karena dapat menghambat pengguna yang perlu memperbesar halaman.
Biarkan normal flow bekerja
Block element secara default memenuhi ruang tersedia dan tersusun vertikal. Ini sudah menjadi fondasi mobile yang kuat. Tambahkan Flexbox atau Grid ketika elemen memang harus berdampingan, bukan untuk setiap pembungkus.
.page {
width: min(100% - 1.25rem, 72rem);
margin-inline: auto;
}
.article-copy {
width: min(100%, 68ch);
}
Lebar maksimum dalam satuan karakter menjaga baris teks tidak terlalu panjang, sedangkan 100% tetap memungkinkan konten menyusut pada layar sempit.
Gunakan ukuran fluid yang mempunyai batas
h1 {
font-size: clamp(2rem, 1.2rem + 4vw, 4.5rem);
}
.section {
padding-block: clamp(2.5rem, 8vw, 6rem);
}
.card {
padding: clamp(1rem, 3vw, 1.5rem);
}
clamp(minimum, preferred, maximum) membuat nilai bertumbuh tanpa menjadi terlalu kecil atau terlalu besar. Pastikan minimum font tetap terbaca dan zoom browser masih bekerja.
Buat galeri yang menentukan jumlah kolom sendiri
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
gap: 1rem;
}
Pola ini tidak membutuhkan breakpoint hanya untuk mengubah 1, 2, dan 3 kolom. Browser menambahkan kolom ketika terdapat ruang minimum 17rem. Breakpoint masih berguna untuk perubahan yang lebih struktural, misalnya memindahkan sidebar ke bawah konten.
Pilih breakpoint berdasarkan tekanan konten
Buka DevTools responsive mode, mulai dari lebar kecil, kemudian tarik viewport perlahan. Ketika navigasi mulai bertabrakan atau kolom artikel menjadi terlalu sempit, catat lebar tersebut dan ubah layout sedikit sebelum titik rusak.
.article-layout {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 2rem;
}
@media (min-width: 56rem) {
.article-layout {
grid-template-columns: minmax(0, 1fr) 16rem;
align-items: start;
}
}
Pendekatan mobile-first bukan kewajiban ideologis, tetapi sering menghasilkan base style yang lebih sederhana. Pilih arah media query yang konsisten agar override mudah dilacak.
Gunakan container query untuk komponen mandiri
Kartu profil dapat muncul di main content yang lebar atau sidebar yang sempit pada viewport sama. Media query tidak mengetahui lebar wadah komponen; container query mengetahuinya.
.profile-region {
container-type: inline-size;
}
.profile-card {
display: grid;
gap: 1rem;
}
@container (min-width: 32rem) {
.profile-card {
grid-template-columns: 8rem minmax(0, 1fr);
align-items: center;
}
}
Gunakan container query ketika variasi komponen bergantung pada ruang parent. Gunakan media query untuk kondisi viewport atau kemampuan input yang memengaruhi halaman secara umum.
Media harus fleksibel dan stabil
img,
video,
svg {
display: block;
max-width: 100%;
}
img,
video {
height: auto;
}
Tetap sertakan atribut width dan height pada gambar agar browser dapat memesan ruang. Gunakan srcset dan sizes ketika satu gambar membutuhkan sumber berbeda berdasarkan lebar render.
<img src="hero-1280.webp"
srcset="hero-640.webp 640w, hero-1280.webp 1280w"
sizes="(max-width: 48rem) 100vw, 50vw"
width="1280" height="720"
alt="Pratinjau layout artikel responsif">
Desain navigasi berdasarkan kemampuan input
Hover tidak tersedia pada banyak layar sentuh. Dropdown kategori harus dapat dibuka melalui klik atau tap dan tetap dapat digunakan dengan keyboard. Gunakan hover sebagai peningkatan pada perangkat yang memang mendukung hover, bukan sebagai satu-satunya cara.
@media (hover: hover) and (pointer: fine) {
.menu-item:hover .submenu {
visibility: visible;
}
}
Tombol menu mobile harus mempunyai area sentuh nyaman, label aksesibel, serta aria-expanded yang disinkronkan. Ketika panel terbuka, jangan membuat halaman melebar ke kanan.
Temukan sumber overflow horizontal
Penyebab umum meliputi fixed width, white-space: nowrap, tabel, blok kode, transform, grid item dengan minimum intrinsik, dan absolute element. Jalankan snippet diagnosis di Console:
const viewport = document.documentElement.clientWidth;
const overflowing = [...document.querySelectorAll("body *")]
.filter((element) => {
const rect = element.getBoundingClientRect();
return rect.left < -1 || rect.right > viewport + 1;
});
console.table(overflowing);
Perbaiki elemen penyebab. Untuk kode dan tabel, scroll internal memang masuk akal. Untuk layout utama, gunakan min-width: 0, track fleksibel, dan media yang tidak melebihi wadah.
Matriks pengujian yang lebih berguna
| Dimensi | Contoh pemeriksaan |
|---|---|
| Lebar | 320, 375, 430, 768, 1280px dan titik di antaranya |
| Tinggi | Ponsel landscape dan layar pendek |
| Teks | Zoom 200%, judul panjang, isi field panjang |
| Input | Sentuh, mouse, keyboard |
| Tema | Light, dark, reduced motion |
| Jaringan | Resource lambat, gambar gagal, JavaScript gagal |
Checklist sebelum deploy
- Tidak ada scroll horizontal pada dokumen utama.
- Teks tidak dipotong dan tetap terbaca ketika zoom.
- Kontrol dapat digunakan tanpa hover.
- Gambar mempunyai dimensi dan tidak menyebabkan layout shift.
- Breakpoint berasal dari kebutuhan konten.
- Urutan DOM tetap logis ketika kolom berpindah.
- Tabel dan kode panjang memiliki scroll internal.