Referensi cepat responsive web design. Media queries, breakpoints, flexbox, grid, dan modern CSS techniques. Must-have buat frontend developer.
Tag HTML yang harus ada di setiap halaman responsive untuk mengontrol bagaimana browser menampilkan halaman pada device mobile.
<!-- Wajib di <head> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Dengan min/max zoom -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0"Berbagai unit pengukuran yang bisa digunakan untuk membuat layout yang responsive terhadap ukuran viewport.
Unit pengukuran fixed yang jarang digunakan untuk responsive design karena tidak menyesuaikan dengan ukuran layar.
/* Fixed (hindari buat responsive) */
px /* Pixels */
pt /* Points */
cm /* Centimeters */Unit pengukuran yang relative terhadap elemen parent atau viewport, ideal untuk responsive design.
/* Relative to parent */
% /* Percentage */
em /* Relative to parent font-size */
/* Relative to root */
rem /* Relative to root font-size */
/* Viewport units */
vw /* 1% of viewport width */
vh /* 1% of viewport height */
vmin /* 1% of smaller dimension */
vmax /* 1% of larger dimension */
/* Container units (modern) */
Contoh penggunaan berbagai unit responsive untuk layout yang fleksibel.
/* Width */
width: 100%; /* Full parent width */
width: 50vw; /* Half viewport width */
max-width: 1200px; /* Max constraint */
/* Font sizes */
font-size: 1rem; /* 16px default */
font-size: 1.5em; /* 1.5x parent size */
font-size: 2vw; /* 2% viewport width */
/* Spacing */
padding: 1rem 2rem;
Teknik CSS untuk menerapkan style berbeda berdasarkan kondisi seperti ukuran layar, orientasi, dll.
Sintaks dasar media queries untuk responsive design dengan mobile-first atau desktop-first approach.
/* Min-width (mobile-first) */
@media (min-width: 768px) {
/* Styles untuk >= 768px */
}
/* Max-width (desktop-first) */
@media (max-width: 767px) {
/* Styles untuk <= 767px */
}
/* Range */
@media (
Breakpoint-breakpoint umum yang sering digunakan untuk responsive design di berbagai framework.
/* Mobile first approach */
/* Mobile (default, no media query) */
.container {
padding: 1rem;
}
/* Small (landscape phones, 576px+) */
@media (min-width: 576px) {
.container
Fitur-fitur media queries modern untuk mendeteksi berbagai kondisi device seperti orientasi, touch capability, dll.
/* Width */
@media (min-width: 768px) { }
@media (max-width: 767px
Cara menggabungkan multiple kondisi dalam satu media query menggunakan AND, OR, dan NOT operators.
/* AND operator */
@media (min-width: 768px) and (max-width: 1023px) { }
/* OR operator (comma) */
@media (max-width: 767px), (min-width: 1200px
Penggunaan Flexbox untuk membuat layout yang responsive dengan berbagai teknik alignment dan spacing.
Setup dasar Flexbox untuk layout responsive yang fleksibel.
.container {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.item {
/* grow shrink basis */
flex: 1 1 300px;
/* or */
/* Mobile: vertical */
.nav {
display: flex;
flex-direction: column;
}
/* Desktop: horizontal */
@media (min-width: 768px) {
.nav {
flex-direction: row;
.cards {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
}
.card {
flex: 1 1 280px; /* Min 280px, auto wrap */
max-width:
.container {
display: flex;
/* Main axis */
justify-content: center;
/* flex-start | flex-end | center | space-between | space-around | space-evenly */
/* Cross axis */
align-items: center;
/* flex-start | flex-end | center | stretch | baseline */
/* Multiple lines */
/* No media queries needed! */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
/* Mobile: 1 column */
.grid {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
}
/* Tablet: 2 columns */
@media (min-width: 768
/* Mobile: stacked */
.layout {
display: grid;
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
gap: 1rem;
}
/* Desktop: sidebar layout */
.grid-container {
display: grid;
/* Columns */
grid-template-columns: 200px 1fr 200px;
grid-template-columns
img {
max-width: 100%;
height: auto;
display: block;
}<!-- Resolution switching -->
<img
src="image-400.jpg"
srcset="
image-400.jpg 400w,
image-800.jpg 800w,
image-1200.jpg 1200w
"
sizes="(max-width: 600px) 400px,
(max-width: 1000px) 800px,
1200px"
alt="Responsive image"
<!-- Art direction -->
<picture>
<source media="(min-width: 1024px)" srcset="desktop.jpg">
<source media="(min-width: 768px)" srcset="tablet.jpg">
<img src
/* Mobile */
.hero {
background-image: url('mobile.jpg');
}
/* Desktop */
@media (min-width: 1024px) {
.hero {
background-image: url('desktop.jpg'
<!-- Native lazy loading -->
<img src="image.jpg" loading="lazy" alt="Lazy loaded">
<!-- Eager loading (default) -->
<img src="hero.jpg" loading="eager" alt="Load immediately">/* Syntax: clamp(min, preferred, max) */
h1 {
font-size: clamp(2rem, 5vw, 4rem);
}
h2 {
font-size: clamp(1.5rem,
/* Mobile */
h1 { font-size: 2rem; }
h2 { font-size: 1.5rem; }
p { font-size: 1rem; }
/* Tablet */
@media (min-width
:root {
--text-xs: clamp(0.75rem, 1.5vw, 0.875rem);
--text-sm: clamp(0.875rem, 2vw, 1
/* Define container */
.card-container {
container-type: inline-size;
container-name: card;
}
/* Query container size */
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 150px
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 1rem;
}
@media (min-width
/* Fluid spacing */
.section {
padding: clamp(2rem, 5vw, 6rem) clamp(1rem, 3vw, 3rem);
}
/* Hide on mobile */
.desktop-only {
display: none;
}
@media (min-width: 1024px) {
.desktop-only {
display: block;
}
}
/* Hide on desktop */
/* Mobile: hamburger menu */
.nav {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height
/* Modern way */
.video-container {
aspect-ratio: 16 / 9;
}
.square {
aspect-ratio: 1 / 1;
}
/* Old way (padding trick) */
.video-container {
position
/* Mobile: stack */
table, thead, tbody, th, td, tr {
display: block;
}
thead {
display:
<style>
/* Inline critical CSS */
.header { ... }
.hero { ... }
</style>
<!-- Defer non-critical CSS -->
<link rel="stylesheet" href="main.css" media="print" onload="this<!-- Preload hero image -->
<link rel="preload" as="image" href="hero.jpg">
<!-- Preload font -->
<link rel="preload" as="font" href="font.woff2" type="font/woff2"<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Optimized">
/* Min 44x44px buat mobile */
.button {
min-height: 44px;
min-width: 44px;
padding: 0.75rem 1.5rem;
}
@media (min-width: 1024px
/* Max 75 characters per line */
.content {
max-width: 65ch; /* ch = character width */
}/* Visible focus for keyboard navigation */
a:focus,
button:focus {
outline: 2px solid blue;
outline-offset: 2px;
}
/* Hide only for mouse users */
a:focus:not(:focus-visible) {
/* Common device sizes untuk testing */
/* Mobile */
/* iPhone SE: 375x667 */
/* iPhone 12/13/14: 390x844 */
/* Samsung Galaxy: 360x800 */
/* Tablet */
/* iPad: 768x1024 */
/* iPad Pro: 1024x1366 */
/* Desktop */
/* Laptop: 1366x768 */
/* Desktop: 1920x1080 */
/* 4K: 3840x2160 *//* Border box buat semua */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* Visual debug */
* {
outline: 1px solid red;
}
/* Logical properties */
padding-inline: 1rem; /* Left + right (LTR) */
padding-block: 2rem; /* Top + bottom */
margin-inline-start: 1rem; /* Left (LTR) */
/* Math functions */
width: min(100%, 1200px);
width: max(300px, 50%);
width: clamp(300px, 50%, 800px);
/* calc() with units */
width: calc(100% - 2rem);
font-size