Web Development

Responsive Web Design: Mobile-First Approach

Panduan lengkap membangun website yang responsif dengan pendekatan Mobile-First β€” media queries, viewport, CSS Grid, Flexbox, breakpoints, dan responsive images

1. Pengenalan Responsive Web Design

Responsive Web Design (RWD) adalah pendekatan desain web yang memastikan halaman web dapat menyesuaikan tampilan dan layoutnya secara otomatis sesuai dengan ukuran dan orientasi layar perangkat yang digunakan β€” mulai dari smartphone kecil hingga monitor ultrawide.

Konsep ini pertama kali dipopulerkan oleh Ethan Marcotte pada tahun 2010 melalui artikel legendarisnya di A List Apart. Sejak saat itu, RWD telah menjadi standar industri dan bahkan menjadi faktor ranking di Google Search (mobile-first indexing).

Mengapa Responsive Design Penting?

Alasan Penjelasan
πŸ“± Mayoritas MobileLebih dari 60% traffic web global berasal dari perangkat mobile
πŸ” SEOGoogle menggunakan mobile-first indexing β€” versi mobile yang dijadikan patokan ranking
πŸ‘€ User ExperiencePengguna meninggalkan situs yang sulit digunakan di mobile dalam hitungan detik
πŸ’° KonversiWebsite responsif meningkatkan tingkat konversi dan mengurangi bounce rate
πŸ”§ MaintenanceSatu codebase untuk semua perangkat β€” lebih mudah di-maintain daripada versi terpisah
🌐 AksesibilitasMemastikan semua orang bisa mengakses konten Anda di perangkat apapun

3 Pilar Responsive Web Design

Diagram: 3 Pilar RWD
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚              RESPONSIVE WEB DESIGN                            β”‚
  β”‚                                                               β”‚
  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
  β”‚  β”‚                  β”‚  β”‚                  β”‚  β”‚            β”‚ β”‚
  β”‚  β”‚  1. FLUID        β”‚  β”‚  2. FLEXIBLE     β”‚  β”‚  3. MEDIA  β”‚ β”‚
  β”‚  β”‚     GRIDS        β”‚  β”‚     IMAGES       β”‚  β”‚   QUERIES  β”‚ β”‚
  β”‚  β”‚                  β”‚  β”‚                  β”‚  β”‚            β”‚ β”‚
  β”‚  β”‚  Layout dengan   β”‚  β”‚  Gambar yang     β”‚  β”‚  CSS rules β”‚ β”‚
  β”‚  β”‚  persen/fr unit  β”‚  β”‚  menyesuaikan    β”‚  β”‚  berdasarkanβ”‚ β”‚
  β”‚  β”‚  bukan px        β”‚  β”‚  ukuran layar    β”‚  β”‚  lebar layarβ”‚ β”‚
  β”‚  β”‚                  β”‚  β”‚                  β”‚  β”‚            β”‚ β”‚
  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
  β”‚                                                               β”‚
  β”‚  + VIEWPORT META TAG (wajib di <head>)                        β”‚
  β”‚  + MOBILE-FIRST CSS (min-width, bukan max-width)             β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Viewport Meta Tag

Viewport meta tag adalah elemen paling penting yang harus ada di setiap halaman web modern. Tanpa tag ini, browser mobile akan menampilkan halaman dalam skala sangat kecil (seolah-olah halaman di-render untuk desktop lalu di-zoom out).

HTML β€” Viewport Meta Tag
<!-- WAJIB ada di setiap halaman web responsif -->
<head>
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0, viewport-fit=cover">
</head>

<!-- Penjelasan setiap properti: -->
<!--
  width=device-width     β†’ Lebar viewport = lebar layar perangkat
  initial-scale=1.0      β†’ Zoom awal 100% (tidak di-zoom)
  viewport-fit=cover     β†’ Menyesuaikan dengan notch/rounded corners
  user-scalable=no       β†’ MENCEGAH zoom (HINDARI β€” masalah aksesibilitas!)
  maximum-scale=1.0      β†’ Membatasi zoom (HINDARI β€” masalah aksesibilitas!)
-->
🚫 Jangan Nonaktifkan Zoom!

Hindari menggunakan user-scalable=no atau maximum-scale=1.0 β€” ini melanggar pedoman aksesibilitas WCAG dan membuat pengguna dengan gangguan penglihatan tidak bisa memperbesar teks. Selalu izinkan zoom!

Viewport Units

CSS β€” Viewport Units
/* vw = viewport width (1vw = 1% dari lebar layar) */
.hero {
    width: 100vw;           /* Lebar penuh layar */
    font-size: 5vw;         /* Font menyesuaikan lebar layar */
}

/* vh = viewport height (1vh = 1% dari tinggi layar) */
.hero {
    min-height: 100vh;      /* Setinggi layar */
    height: 50vh;           /* Setengah tinggi layar */
}

/* vmin = nilai terkecil antara vw dan vh */
.element {
    font-size: 4vmin;       /* 4% dari sisi terpendek */
}

/* vmax = nilai terbesar antara vw dan vh */
.element {
    padding: 2vmax;         /* 2% dari sisi terpanjang */
}

/* Contoh: Hero section full-screen */
.hero-section {
    min-height: 100vh;
    min-height: 100dvh;  /* dvh = dynamic viewport height (mengabaikan toolbar) */
    display: flex;
    align-items: center;
    justify-content: center;
}

3. Mobile-First Approach

Mobile-First adalah pendekatan desain di mana Anda menulis CSS untuk perangkat mobile terlebih dahulu, lalu secara bertahap menambahkan gaya untuk layar yang lebih besar menggunakan min-width media queries. Ini kebalikan dari pendekatan lama (desktop-first) yang menggunakan max-width.

Mengapa Mobile-First?

Aspek Mobile-First (min-width) Desktop-First (max-width)
PrioritasMemaksa Anda memprioritaskan konten pentingCenderung membuang elemen dari desktop
PerformaCSS dasar ringan, ditambah seiring layar membesarCSS desktop di-load duluan, lalu di-override
KodeLebih bersih β€” progressive enhancementCenderung lebih banyak override
Mindset"Apa yang ESSENSIAL?""Apa yang harus DIHAPUS?"
GoogleSejalan dengan mobile-first indexingBisa bermasalah untuk SEO

Mobile-First dalam Praktik

CSS β€” Mobile-First CSS
/* ========================================
   MOBILE FIRST β€” Default styles untuk mobile
   ======================================== */

/* Base styles (mobile) β€” TANPA media query */
.container {
    width: 100%;
    padding: 0 1rem;
    margin: 0 auto;
}

h1 {
    font-size: 1.75rem;
    line-height: 1.2;
    margin-bottom: 1rem;
}

p {
    font-size: 1rem;
    line-height: 1.6;
    margin-bottom: 1rem;
    color: #6b7280;
}

.card-grid {
    display: grid;
    grid-template-columns: 1fr;  /* 1 kolom di mobile */
    gap: 1rem;
}

.navbar {
    padding: 0.75rem 1rem;
}

/* ========================================
   TABLET β€” min-width 768px
   ======================================== */
@media (min-width: 768px) {
    .container {
        max-width: 720px;
        padding: 0 1.5rem;
    }

    h1 {
        font-size: 2.25rem;
    }

    .card-grid {
        grid-template-columns: repeat(2, 1fr);  /* 2 kolom */
        gap: 1.5rem;
    }

    .navbar {
        padding: 1rem 2rem;
    }
}

/* ========================================
   DESKTOP β€” min-width 1024px
   ======================================== */
@media (min-width: 1024px) {
    .container {
        max-width: 960px;
        padding: 0 2rem;
    }

    h1 {
        font-size: 2.75rem;
    }

    .card-grid {
        grid-template-columns: repeat(3, 1fr);  /* 3 kolom */
        gap: 2rem;
    }
}

/* ========================================
   LARGE DESKTOP β€” min-width 1280px
   ======================================== */
@media (min-width: 1280px) {
    .container {
        max-width: 1200px;
    }

    h1 {
        font-size: 3rem;
    }

    .card-grid {
        grid-template-columns: repeat(4, 1fr);  /* 4 kolom */
    }
}
πŸ’‘ Tips Mobile-First

Saat menulis mobile-first, tanyakan pada diri sendiri: "Jika hanya satu elemen yang bisa saya tampilkan di layar kecil, apa yang paling penting?" Jawabannya adalah elemen yang harus paling menonjol di CSS dasar (tanpa media query). Elemen lain ditambahkan secara progresif untuk layar lebih besar.

4. Media Queries

Media queries adalah fitur CSS yang memungkinkan Anda menerapkan gaya berbeda berdasarkan karakteristik perangkat β€” terutama lebar layar, tinggi layar, orientasi (portrait/landscape), dan kemampuan perangkat (hover, pointer).

Sintaks Media Query

CSS β€” Media Queries
/* ===== Sintaks Dasar ===== */
@media (kondisi) {
    /* CSS yang hanya diterapkan jika kondisi terpenuhi */
}

/* ===== min-width: Lebar MINIMUM (mobile-first) ===== */
@media (min-width: 768px) {
    /* Diterapkan jika layar LEBIH DARI SAMA DENGAN 768px */
    /* Berlaku untuk tablet dan desktop */
}

/* ===== max-width: Lebar MAKSIMUM (desktop-first / override) ===== */
@media (max-width: 767px) {
    /* Diterapkan jika layar KURANG DARI 768px */
    /* Hanya untuk mobile */
}

/* ===== Kombinasi kondisi (AND) ===== */
@media (min-width: 768px) and (max-width: 1023px) {
    /* Hanya untuk tablet (768px - 1023px) */
}

/* ===== Orientasi ===== */
@media (orientation: portrait) {
    /* Layar lebih tinggi dari lebar (mobile portrait) */
    body { font-size: 16px; }
}

@media (orientation: landscape) {
    /* Layar lebih lebar dari tinggi */
    body { font-size: 14px; }
}

/* ===== Hover capability ===== */
@media (hover: hover) {
    /* Perangkat dengan mouse/trackpad */
    .button:hover {
        background: #1d4ed8;
    }
}

@media (hover: none) {
    /* Perangkat touchscreen */
    .button {
        padding: 12px 24px;  /* Tombol lebih besar untuk sentuhan */
    }
}

/* ===== Pointer precision ===== */
@media (pointer: fine) {
    /* Mouse β€” presisi tinggi */
}

@media (pointer: coarse) {
    /* Jari β€” presisi rendah, butuh target lebih besar */
    .button { min-height: 44px; min-width: 44px; }
}

/* ===== prefers-color-scheme (dark mode) ===== */
@media (prefers-color-scheme: dark) {
    :root {
        --bg-color: #0f172a;
        --text-color: #e2e8f0;
    }
}

@media (prefers-color-scheme: light) {
    :root {
        --bg-color: #ffffff;
        --text-color: #1e293b;
    }
}

/* ===== prefers-reduced-motion ===== */
@media (prefers-reduced-motion: reduce) {
    * {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}

Kombinasi Media Query

CSS β€” Combined Media Queries
/* AND operator (koma = OR) */
@media (min-width: 768px) and (orientation: landscape) {
    /* Tablet dalam mode landscape */
}

/* OR operator (koma) */
@media (max-width: 767px), (orientation: portrait) {
    /* Mobile ATAU portrait mode */
}

/* NOT operator */
@media not print {
    /* Semua kecuali print */
}

/* Contoh: Print styles */
@media print {
    .navbar, .footer, .ad-slot, .back-to-top {
        display: none !important;
    }

    body {
        font-size: 12pt;
        color: black;
        background: white;
    }

    a[href]::after {
        content: " (" attr(href) ")";
    }
}

5. Breakpoints Standar

Breakpoint adalah titik lebar layar di mana layout berubah. Pemilihan breakpoint yang tepat memastikan website terlihat baik di semua perangkat populer.

Breakpoints yang Direkomendasikan

Nama Range Perangkat CSS
πŸ“± Mobile Small< 375pxiPhone SE, Android kecildefault (base)
πŸ“± Mobile375px β€” 767pxiPhone, Android rata-ratadefault (base)
πŸ“² Tablet Portrait768px β€” 1023pxiPad, tablet Android@media (min-width: 768px)
πŸ’» Desktop1024px β€” 1279pxLaptop, desktop@media (min-width: 1024px)
πŸ–₯️ Large Desktop1280px β€” 1535pxMonitor besar@media (min-width: 1280px)
πŸ–₯️ Extra Largeβ‰₯ 1536pxUltrawide, 4K@media (min-width: 1536px)
CSS β€” Breakpoints dengan CSS Custom Properties
/* Membuat breakpoint sebagai custom properties agar konsisten */
:root {
    --bp-sm: 640px;
    --bp-md: 768px;
    --bp-lg: 1024px;
    --bp-xl: 1280px;
    --bp-2xl: 1536px;
}

/* Menggunakan (hanya bisa di media query level 4) */
/* Catatan: Tidak semua browser mendukung custom properties di media query */

/* Pendekatan yang lebih aman β€” gunakan angka langsung */
/* Mobile-first breakpoints */

/* Base: 0 - 767px (mobile) */
.grid { grid-template-columns: 1fr; }

/* sm: 640px+ */
@media (min-width: 640px) {
    .grid { grid-template-columns: repeat(2, 1fr); }
}

/* md: 768px+ */
@media (min-width: 768px) {
    .grid { grid-template-columns: repeat(2, 1fr); }
}

/* lg: 1024px+ */
@media (min-width: 1024px) {
    .grid { grid-template-columns: repeat(3, 1fr); }
}

/* xl: 1280px+ */
@media (min-width: 1280px) {
    .grid { grid-template-columns: repeat(4, 1fr); }
}

/* 2xl: 1536px+ */
@media (min-width: 1536px) {
    .container { max-width: 1440px; }
}
πŸ“– Tips Memilih Breakpoint

Jangan menargetkan perangkat spesifik (misalnya "iPhone 14 Pro"). Sebaliknya, letakkan breakpoint di mana layout Anda mulai terlihat rusak. Setiap desain punya breakpoint yang berbeda tergantung kontennya. Gunakan DevTools (F12 β†’ Responsive Mode) untuk menguji berbagai ukuran layar.

6. CSS Grid Responsive

CSS Grid memiliki fitur canggih yang memungkinkan layout menjadi responsif bahkan tanpa media queries β€” menggunakan auto-fill, auto-fit, dan minmax().

Responsive Grid Tanpa Media Query

CSS β€” Auto-responsive Grid
/* ===== Magic Grid: Responsif tanpa media query ===== */
.auto-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 1.5rem;
    padding: 1.5rem;
}

/* Penjelasan:
 * repeat()      β€” mengulang pola kolom
 * auto-fill     β€” buat kolom sebanyak MUngkin berdasarkan lebar container
 * minmax(280px, 1fr) β€” setiap kolom minimum 280px, maksimum 1fr (sama rata)
 *
 * Hasil:
 * - Layar 320px  β†’ 1 kolom (280px min, sisa < 280px = 1 kolom)
 * - Layar 640px  β†’ 2 kolom (280px + 280px = 560px, sisa 80px)
 * - Layar 960px  β†’ 3 kolom (280px Γ— 3 = 840px)
 * - Layar 1280px β†’ 4 kolom (280px Γ— 4 = 1120px)
 */

/* auto-fill vs auto-fit */
.auto-fill-example {
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    /* auto-fill: kolom KOSONG tetap ada jika ada ruang */
}

.auto-fit-example {
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    /* auto-fit: kolom kosong DIHAPUS, item meregang penuh */
    /* Biasanya ini yang lebih diinginkan */
}

Responsive Grid Layout Halaman

CSS β€” Responsive Page Layout
/* ===== Layout Halaman Responsif ===== */

/* Mobile: Stack vertikal */
.page {
    display: grid;
    grid-template-columns: 1fr;
    grid-template-areas:
        "header"
        "nav"
        "main"
        "sidebar"
        "footer";
    min-height: 100vh;
}

/* Tablet: Sidebar di bawah */
@media (min-width: 768px) {
    .page {
        grid-template-columns: 1fr 250px;
        grid-template-areas:
            "header  header"
            "nav     nav"
            "main    sidebar"
            "footer  footer";
    }
}

/* Desktop: Sidebar di samping */
@media (min-width: 1024px) {
    .page {
        grid-template-columns: 250px 1fr 280px;
        grid-template-areas:
            "header  header  header"
            "nav     main    sidebar"
            "footer  footer  footer";
    }
}

.page-header  { grid-area: header; }
.page-nav     { grid-area: nav; }
.page-main    { grid-area: main; }
.page-sidebar { grid-area: sidebar; }
.page-footer  { grid-area: footer; }

Contoh: Gallery Grid Responsif

HTML + CSS β€” Responsive Gallery
<div class="gallery">
    <div class="gallery-item"><img src="1.jpg" alt="Foto 1"></div>
    <div class="gallery-item"><img src="2.jpg" alt="Foto 2"></div>
    <div class="gallery-item"><img src="3.jpg" alt="Foto 3"></div>
    <div class="gallery-item featured"><img src="4.jpg" alt="Foto 4"></div>
    <div class="gallery-item"><img src="5.jpg" alt="Foto 5"></div>
    <div class="gallery-item"><img src="6.jpg" alt="Foto 6"></div>
</div>

<style>
.gallery {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 1rem;
    padding: 1rem;
}

.gallery-item img {
    width: 100%;
    height: 200px;
    object-fit: cover;
    border-radius: 8px;
}

/* Item featured mengambil 2 kolom di desktop */
@media (min-width: 1024px) {
    .gallery {
        grid-template-columns: repeat(3, 1fr);
    }
    .gallery-item.featured {
        grid-column: span 2;
        grid-row: span 2;
    }
    .gallery-item.featured img {
        height: 100%;
    }
}
</style>

7. Flexbox Responsive

Flexbox sangat berguna untuk membuat komponen responsif seperti navigasi, card layouts, dan form yang menyesuaikan diri berdasarkan ruang yang tersedia.

Responsive Navbar

HTML + CSS β€” Responsive Navbar
<nav class="navbar-responsive">
    <div class="brand">BeebaneLabs</div>
    <button class="menu-btn" onclick="toggleMenu()">☰</button>
    <ul class="nav-links">
        <li><a href="#">Beranda</a></li>
        <li><a href="#">Tutorial</a></li>
        <li><a href="#">Blog</a></li>
        <li><a href="#">Kontak</a></li>
    </ul>
</nav>

<style>
.navbar-responsive {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    padding: 0.75rem 1rem;
    background: #1e293b;
}

.brand {
    font-size: 1.25rem;
    font-weight: 700;
    color: white;
}

.menu-btn {
    display: block;  /* Tampil di mobile */
    background: none;
    border: none;
    color: white;
    font-size: 1.5rem;
    cursor: pointer;
}

.nav-links {
    display: none;  /* Tersembunyi di mobile */
    list-style: none;
    width: 100%;
    flex-direction: column;
    gap: 0.5rem;
    padding: 1rem 0 0;
}

.nav-links.active {
    display: flex;  /* Tampil saat tombol diklik */
}

.nav-links a {
    color: #94a3b8;
    text-decoration: none;
    display: block;
    padding: 0.5rem 0;
}

/* Desktop: tampil horizontal */
@media (min-width: 768px) {
    .menu-btn { display: none; }
    .nav-links {
        display: flex !important;
        flex-direction: row;
        width: auto;
        gap: 1.5rem;
        padding: 0;
    }
}
</style>

Responsive Card Layout dengan Flexbox

CSS β€” Flexbox Cards
.card-container {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    justify-content: center;
    padding: 1.5rem;
}

.card {
    /* flex: grow shrink basis */
    flex: 1 1 300px;  /* Minimum 300px, bisa grow */
    max-width: 400px;  /* Maksimum 400px */
    background: #1e293b;
    border-radius: 12px;
    padding: 1.5rem;
    color: white;
}

.card img {
    width: 100%;
    height: 180px;
    object-fit: cover;
    border-radius: 8px;
    margin-bottom: 1rem;
}

.card h3 {
    font-size: 1.125rem;
    margin-bottom: 0.5rem;
}

.card p {
    font-size: 0.875rem;
    color: #94a3b8;
    line-height: 1.6;
}

/* Hasil:
 * - Mobile (320px):  1 card per baris (basis 300px)
 * - Tablet (768px):  2 cards per baris (300+300+gap)
 * - Desktop (1200px): 3 cards per baris
 */
πŸ’‘ Flexbox vs Grid untuk Cards

Gunakan Flexbox jika Anda ingin card memiliki lebar fleksibel yang menyesuaikan ruang. Gunakan Grid dengan auto-fit jika Anda ingin card memiliki lebar yang konsisten dan kolom yang seragam. Keduanya valid β€” tergantung desain yang diinginkan.

8. Responsive Images

Gambar sering menjadi elemen terberat di halaman web. Mengirim gambar berukuran desktop ke perangkat mobile membuang bandwidth dan memperlambat loading. Responsive images memastikan gambar yang tepat dikirim ke perangkat yang tepat.

Teknik Responsive Images

HTML β€” Responsive Images
<!-- 1. Basic: max-width 100% (paling sederhana) -->
<style>
.responsive-img {
    max-width: 100%;
    height: auto;
    display: block;
}
</style>
<img src="foto.jpg" alt="Deskripsi" class="responsive-img">

<!-- 2. srcset: Beda resolusi, gambar sama -->
<img src="foto-800.jpg"
     srcset="foto-400.jpg 400w,
             foto-800.jpg 800w,
             foto-1200.jpg 1200w,
             foto-1600.jpg 1600w"
     sizes="(max-width: 600px) 100vw,
            (max-width: 1200px) 50vw,
            33vw"
     alt="Foto dengan multiple resolusi"
     class="responsive-img">

<!-- 3. picture: Beda gambar untuk beda layar -->
<picture>
    <!-- Format WebP (lebih kecil, browser modern) -->
    <source srcset="foto.webp" type="image/webp">
    <!-- Format AVIF (paling kecil) -->
    <source srcset="foto.avif" type="image/avif">
    <!-- Fallback untuk browser lama -->
    <img src="foto.jpg" alt="Deskripsi" class="responsive-img">
</picture>

<!-- 4. Art Direction: Gambar berbeda per breakpoint -->
<picture>
    <!-- Mobile: gambar potrait/cropped -->
    <source media="(max-width: 767px)"
            srcset="hero-mobile.jpg">
    <!-- Tablet: gambar medium -->
    <source media="(max-width: 1023px)"
            srcset="hero-tablet.jpg">
    <!-- Desktop: gambar penuh -->
    <img src="hero-desktop.jpg" alt="Hero image" class="responsive-img">
</picture>

Object-fit untuk Gambar

CSS β€” object-fit
/* object-fit: mengontrol bagaimana gambar mengisi container */
.card-img {
    width: 100%;
    height: 200px;         /* Tinggi tetap */
    object-fit: cover;      /* Memotong gambar agar pas */
    object-position: center; /* Posisi crop */
    border-radius: 8px;
}

/* object-fit values:
 * cover     β†’ Mengisi penuh, memotong bagian yang berlebih
 * contain   β†’ Menampilkan seluruh gambar, mungkin ada ruang kosong
 * fill      β†’ Meregangkan gambar (bisa distort)
 * none      β†’ Ukuran asli gambar
 * scale-down β†’ Paling kecil antara none dan contain
 */

/* Avatar lingkaran */
.avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    object-fit: cover;
    object-position: top;  /* Fokus ke wajah (biasanya di atas) */
}

Lazy Loading

HTML β€” Lazy Loading
<!-- loading="lazy" β€” gambar hanya di-load saat mendekati viewport -->
<img src="foto.jpg" alt="Deskripsi" loading="lazy"
     width="800" height="600">

<!-- Selalu tentukan width dan height untuk mencegah layout shift -->
<!-- Aspect ratio dihitung dari width/height -->

<!-- fetchpriority: prioritaskan gambar hero -->
<img src="hero.jpg" alt="Hero" loading="eager" fetchpriority="high">

<!-- Gambar di bawah fold: lazy + low priority -->
<img src="footer-img.jpg" alt="Footer" loading="lazy" fetchpriority="low">
⚠️ Layout Shift (CLS)

Selalu tentukan atribut width dan height pada tag <img>. Tanpa atribut ini, browser tidak tahu rasio aspek gambar sebelum gambar dimuat β€” menyebabkan layout berpindah-pindah (layout shift) yang merusak pengalaman pengguna dan skor Core Web Vitals.

9. Fluid Typography & Units

Fluid typography adalah teknik membuat ukuran teks berubah secara halus (smooth) antar breakpoint β€” bukan melompat tiba-tiba saat mencapai breakpoint. Ini memberikan pengalaman membaca yang lebih baik di semua ukuran layar.

clamp() Function

CSS β€” Fluid Typography
/* clamp(minimum, ideal, maksimum) */
/* Ideal bisa berupa viewport unit (vw) */

/* Heading fluid */
h1 {
    font-size: clamp(1.75rem, 4vw, 3.5rem);
    /* Minimum: 1.75rem (28px)
     * Ideal:   4% dari lebar viewport
     * Maks:    3.5rem (56px)
     *
     * Di HP 375px:   4vw = 15px  β†’ clamp = 1.75rem (28px) β€” pakai minimum
     * Di tablet 768px: 4vw = 30.7px β†’ clamp = 30.7px β€” pakai ideal
     * Di desktop 1440px: 4vw = 57.6px β†’ clamp = 3.5rem (56px) β€” pakai maks
     */
}

h2 {
    font-size: clamp(1.5rem, 3vw, 2.5rem);
}

h3 {
    font-size: clamp(1.25rem, 2.5vw, 1.75rem);
}

p {
    font-size: clamp(1rem, 1.5vw, 1.125rem);
    line-height: 1.7;
}

/* Spacing fluid */
.section {
    padding: clamp(2rem, 5vw, 6rem) clamp(1rem, 3vw, 4rem);
}

/* Gap fluid */
.grid {
    gap: clamp(1rem, 2vw, 2rem);
}

/* Container fluid */
.container {
    width: min(90%, 1200px);
    /* 90% dari viewport, maksimal 1200px */
    margin: 0 auto;
}

Praktik Terbaik Responsive

CSS β€” Responsive Best Practices
/* ===== 1. Reset box-sizing ===== */
*, *::before, *::after {
    box-sizing: border-box;
}

/* ===== 2. Base font size fluid ===== */
html {
    font-size: clamp(15px, 1.5vw, 18px);
}

/* ===== 3. Container responsif ===== */
.container {
    width: min(90%, 1200px);
    margin: 0 auto;
    padding-inline: clamp(1rem, 3vw, 2rem);
}

/* ===== 4. Gambar responsif ===== */
img, video, svg {
    max-width: 100%;
    height: auto;
    display: block;
}

/* ===== 5. Form responsif ===== */
input, select, textarea {
    width: 100%;
    font-size: 1rem;        /* Mencegah zoom di iOS */
    padding: 0.75rem;
}

/* ===== 6. Target sentuhan yang cukup besar ===== */
button, a, input[type="submit"] {
    min-height: 44px;       /* 44px minimum untuk touch target */
    min-width: 44px;
}

/* ===== 7. Overflow horizontal ===== */
body {
    overflow-x: hidden;     /* Mencegah scroll horizontal */
}

/* ===== 8. Tabel responsif ===== */
.table-wrapper {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* ===== 9. Video responsif ===== */
.video-wrapper {
    position: relative;
    padding-bottom: 56.25%; /* 16:9 aspect ratio */
    height: 0;
    overflow: hidden;
}

.video-wrapper iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
πŸš€ Testing Responsive Design

Gunakan Chrome DevTools (F12 β†’ ikon toggle device toolbar) untuk menguji responsive design di berbagai ukuran layar. Aktifkan juga Network throttling untuk mensimulasikan koneksi lambat di mobile. Selalu test di perangkat nyata juga β€” emulator tidak 100% akurat.

10. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang Responsive Web Design:

Pertanyaan 1: Apa fungsi utama dari <meta name="viewport">?

a) Mengatur zoom halaman di desktop
b) Memberitahu browser cara mengatur dimensi dan skala viewport di perangkat mobile
c) Mengubah resolusi gambar di halaman
d) Mengoptimalkan performa JavaScript

Pertanyaan 2: Dalam pendekatan Mobile-First, media query menggunakan fungsi apa untuk menargetkan layar yang lebih besar?

a) max-width
b) min-width
c) exact-width
d) viewport-width

Pertanyaan 3: Apa perbedaan antara auto-fill dan auto-fit di CSS Grid?

a) auto-fill untuk mobile, auto-fit untuk desktop
b) auto-fill membuat kolom kosong tetap ada, auto-fit meruntuhkan kolom kosong sehingga item meregang penuh
c) Tidak ada perbedaan, keduanya sama
d) auto-fill lebih cepat loading-nya

Pertanyaan 4: Apa output dari clamp(1rem, 3vw, 2rem) pada layar dengan lebar 200px?

a) 2rem (maksimum)
b) 6px (3% dari 200px)
c) 1rem / 16px (minimum)
d) 3vw

Pertanyaan 5: Mengapa atribut width dan height pada tag <img> penting untuk responsive design?

a) Untuk mengatur ukuran gambar agar tetap fixed
b) Untuk mencegah layout shift (CLS) saat gambar dimuat
c) Untuk mempercepat loading gambar
d) Untuk mengompresi ukuran file gambar