Responsive Design
Fluid Typography with clamp()
Replace media query breakpoints for font sizes:
/* min 1rem, preferred 2.5vw, max 2rem */
h1 { font-size: clamp(1rem, 2.5vw + 0.5rem, 2rem); }
/* fluid spacing */
.section { padding: clamp(1rem, 5vw, 3rem); }
Container Queries
Style based on parent container size instead of viewport:
.card-wrapper {
container-type: inline-size;
container-name: card;
}
@container card (min-width: 400px) {
.card { flex-direction: row; }
}
@container card (max-width: 399px) {
.card { flex-direction: column; }
}
Media Queries – Beyond Width
/* Prefers reduced motion */
@media (prefers-reduced-motion: reduce) {
* { animation-duration: 0.01ms !important; }
}
/* Dark mode */
@media (prefers-color-scheme: dark) {
:root { --bg: #1a1a1a; --text: #f0f0f0; }
}
/* Hover capability (touch vs mouse) */
@media (hover: hover) {
.btn:hover { background: var(--hover-bg); }
}
/* High DPI screens */
@media (min-resolution: 2dppx) {
.logo { background-image: url('logo@2x.png'); }
}
Viewport Units
| Unit | Meaning |
|---|---|
vw / vh | 1% of viewport width / height |
dvh | Dynamic viewport height (accounts for mobile URL bar) |
svh | Small viewport height (URL bar visible) |
lvh | Large viewport height (URL bar hidden) |
.hero {
min-height: 100dvh; /* works correctly on mobile */
}
Logical Properties
Write direction-agnostic CSS for internationalization:
.card {
margin-block: 1rem; /* top + bottom */
margin-inline: 2rem; /* left + right (or right + left in RTL) */
padding-inline-start: 1rem; /* left in LTR, right in RTL */
border-block-end: 1px solid; /* bottom border */
}