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) */
cqw /* 1% of container width */
cqh /* 1% of container height */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;
margin: 2rem auto;
gap: 1.5rem;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 (min-width: 768px) and (max-width: 1023px) {
/* Styles untuk tablet aja */
}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 {
max-width: 540px;
}
}
/* Medium (tablets, 768px+) */
@media (min-width: 768px) {
.container {
max-width: 720px;
}
}
/* Large (desktops, 992px+) */
@media (min-width: 992px) {
.container {
max-width: 960px;
}
}
/* Extra large (large desktops, 1200px+) */
@media (min-width: 1200px) {
.container {
max-width: 1140px;
}
}
/* 2XL (1400px+) */
@media (min-width: 1400px) {
.container {
max-width: 1320px;
}
}Fitur-fitur media queries modern untuk mendeteksi berbagai kondisi device seperti orientasi, touch capability, dll.
/* Width */
@media (min-width: 768px) { }
@media (max-width: 767px) { }
/* Height */
@media (min-height: 600px) { }
@media (max-height: 800px) { }
/* Orientation */
@media (orientation: landscape) { }
@media (orientation: portrait) { }
/* Aspect ratio */
@media (aspect-ratio: 16/9) { }
@media (min-aspect-ratio: 16/9) { }
/* Hover capability */
@media (hover: hover) {
/* Device supports hover */
.button:hover {
background: blue;
}
}
@media (hover: none) {
/* Touch device, no hover */
}
/* Pointer precision */
@media (pointer: fine) {
/* Mouse/trackpad (precise) */
}
@media (pointer: coarse) {
/* Touch (not precise) */
}
/* Display mode */
@media (display-mode: fullscreen) { }
@media (display-mode: standalone) {
/* PWA installed */
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}
/* Color scheme preference */
@media (prefers-color-scheme: dark) {
/* Dark mode */
}
@media (prefers-color-scheme: light) {
/* Light mode */
}
/* High DPI / Retina */
@media (-webkit-min-device-pixel-ratio: 2),
(min-resolution: 192dpi),
(min-resolution: 2dppx) {
/* Retina displays */
}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) { }
/* NOT operator */
@media not all and (min-width: 768px) { }
/* Combining features */
@media (min-width: 768px) and (orientation: landscape) { }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 */
flex-grow: 1;
flex-shrink: 1;
flex-basis: 300px;
}/* 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: 400px; /* Max per card */
}.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 */
align-content: center;
/* Same values as align-items */
}
/* Individual item alignment */
.item {
align-self: flex-start;
}/* No media queries needed! */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
/* auto-fill vs auto-fit */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* Creates empty columns */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); /* Stretches items *//* Mobile: 1 column */
.grid {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
}
/* Tablet: 2 columns */
@media (min-width: 768px) {
.grid {
grid-template-columns: repeat(2, 1fr);
gap: 1.5rem;
}
}
/* Desktop: 3 columns */
@media (min-width: 1024px) {
.grid {
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
}
}/* Mobile: stacked */
.layout {
display: grid;
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
gap: 1rem;
}
/* Desktop: sidebar layout */
@media (min-width: 1024px) {
.layout {
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
grid-template-columns: 250px 1fr;
}
}
.header { grid-area: header; }
.main { grid-area: main; }
.sidebar { grid-area: sidebar; }
.footer { grid-area: footer; }.grid-container {
display: grid;
/* Columns */
grid-template-columns: 200px 1fr 200px;
grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
/* Rows */
grid-template-rows: 100px auto 50px;
grid-auto-rows: minmax(100px, auto);
/* Gap */
gap: 1rem;
column-gap: 1rem;
row-gap: 0.5rem;
/* Alignment */
justify-items: center; /* Horizontal align items */
align-items: center; /* Vertical align items */
justify-content: center; /* Horizontal align grid */
align-content: center; /* Vertical align grid */
}
.grid-item {
/* Position */
grid-column: 1 / 3; /* Span columns 1-2 */
grid-row: 1 / 2; /* Span row 1 */
/* or */
grid-column: span 2; /* Span 2 columns */
grid-row: span 1; /* Span 1 row */
/* Alignment */
justify-self: start; /* Align this item horizontally */
align-self: start; /* Align this item vertically */
}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"
/>
<!-- Pixel density -->
<img
src="image.jpg"
srcset="
image.jpg 1x,
image@2x.jpg 2x,
image@3x.jpg 3x
"
alt="Retina ready"
/><!-- Art direction -->
<picture>
<source media="(min-width: 1024px)" srcset="desktop.jpg">
<source media="(min-width: 768px)" srcset="tablet.jpg">
<img src="mobile.jpg" alt="Responsive">
</picture>
<!-- WebP with fallback -->
<picture>
<source srcset="image.webp" type="image/webp">
<source srcset="image.jpg" type="image/jpeg">
<img src="image.jpg" alt="Modern format">
</picture>/* Mobile */
.hero {
background-image: url('mobile.jpg');
}
/* Desktop */
@media (min-width: 1024px) {
.hero {
background-image: url('desktop.jpg');
}
}
/* Retina */
@media (-webkit-min-device-pixel-ratio: 2),
(min-resolution: 192dpi) {
.hero {
background-image: url('desktop@2x.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, 4vw, 3rem);
}
p {
font-size: clamp(1rem, 2.5vw, 1.25rem);
line-height: clamp(1.5, 3vw, 1.75);
}
/* Spacing dengan clamp */
.section {
padding: clamp(2rem, 5vw, 6rem) clamp(1rem, 3vw, 3rem);
}/* Mobile */
h1 { font-size: 2rem; }
h2 { font-size: 1.5rem; }
p { font-size: 1rem; }
/* Tablet */
@media (min-width: 768px) {
h1 { font-size: 3rem; }
h2 { font-size: 2rem; }
p { font-size: 1.125rem; }
}
/* Desktop */
@media (min-width: 1024px) {
h1 { font-size: 4rem; }
h2 { font-size: 2.5rem; }
p { font-size: 1.25rem; }
}:root {
--text-xs: clamp(0.75rem, 1.5vw, 0.875rem);
--text-sm: clamp(0.875rem, 2vw, 1rem);
--text-base: clamp(1rem, 2.5vw, 1.125rem);
--text-lg: clamp(1.125rem, 3vw, 1.25rem);
--text-xl: clamp(1.25rem, 3.5vw, 1.5rem);
--text-2xl: clamp(1.5rem, 4vw, 2rem);
--text-3xl: clamp(2rem, 5vw, 3rem);
--text-4xl: clamp(2.5rem, 6vw, 4rem);
}
h1 { font-size: var(--text-4xl); }
h2 { font-size: var(--text-3xl); }
h3 { font-size: var(--text-2xl); }
p { font-size: var(--text-base); }/* 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 1fr;
}
}
@container card (min-width: 600px) {
.card {
grid-template-columns: 200px 1fr;
}
}
/* Container query units */
.card-title {
font-size: clamp(1rem, 5cqw, 2rem); /* 5% of container width */
}.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 1rem;
}
@media (min-width: 768px) {
.container {
padding: 0 2rem;
}
}
@media (min-width: 1024px) {
.container {
padding: 0 3rem;
}
}/* Fluid spacing */
.section {
padding: clamp(2rem, 5vw, 6rem) clamp(1rem, 3vw, 3rem);
}
/* or with breakpoints */
.section {
padding: 2rem 1rem;
}
@media (min-width: 768px) {
.section {
padding: 4rem 2rem;
}
}
@media (min-width: 1024px) {
.section {
padding: 6rem 3rem;
}
}/* Hide on mobile */
.desktop-only {
display: none;
}
@media (min-width: 1024px) {
.desktop-only {
display: block;
}
}
/* Hide on desktop */
.mobile-only {
display: block;
}
@media (min-width: 1024px) {
.mobile-only {
display: none;
}
}/* Mobile: hamburger menu */
.nav {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: white;
}
.nav.active {
display: flex;
flex-direction: column;
}
/* Desktop: horizontal */
@media (min-width: 768px) {
.nav {
display: flex !important;
position: static;
flex-direction: row;
height: auto;
}
.hamburger {
display: none;
}
}/* Modern way */
.video-container {
aspect-ratio: 16 / 9;
}
.square {
aspect-ratio: 1 / 1;
}
/* Old way (padding trick) */
.video-container {
position: relative;
padding-bottom: 56.25%; /* 16:9 ratio */
height: 0;
}
.video-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}/* Mobile: stack */
table, thead, tbody, th, td, tr {
display: block;
}
thead {
display: none;
}
td {
position: relative;
padding-left: 50%;
}
td::before {
content: attr(data-label);
position: absolute;
left: 0;
width: 45%;
font-weight: bold;
}
/* Desktop: normal table */
@media (min-width: 768px) {
table, thead, tbody, th, td, tr {
display: table;
display: table-row-group;
display: table-row;
display: table-cell;
}
thead {
display: table-header-group;
}
td {
padding-left: 1rem;
}
td::before {
display: none;
}
}<style>
/* Inline critical CSS */
.header { ... }
.hero { ... }
</style>
<!-- Defer non-critical CSS -->
<link rel="stylesheet" href="main.css" media="print" onload="this.media='all'"><!-- Preload hero image -->
<link rel="preload" as="image" href="hero.jpg">
<!-- Preload font -->
<link rel="preload" as="font" href="font.woff2" type="font/woff2" crossorigin><picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Optimized">
</picture>/* Min 44x44px buat mobile */
.button {
min-height: 44px;
min-width: 44px;
padding: 0.75rem 1.5rem;
}
@media (min-width: 1024px) {
.button {
min-height: 38px;
min-width: 38px;
}
}/* 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) {
outline: none;
}/* 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;
}
/* Check overflow */
* {
outline: 1px solid rgba(255, 0, 0, 0.2);
}/* 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: calc(1rem + 0.5vw);
/* Custom properties */
:root {
--spacing: clamp(1rem, 3vw, 3rem);
}
.section {
padding: var(--spacing);
}Login atau daftar akun gratis untuk membaca cheat sheet ini.