Fluid Typography with clamp()
Fluid typography scales smoothly with viewport width without media queries, using the clamp() function. This creates better readability across all devices: smaller on phones, larger on desktops, with smooth scaling in between. It's more elegant than media query breakpoints.
Introduction to fluid typography
CSS
<!-- clamp: (min, preferred, max) -->
.heading {
font-size: clamp(24px, 5vw, 48px);
/* Min: 24px (smallest screen) -->
/* Preferred: 5% of viewport width -->
/* Max: 48px (largest screen) -->
}
<!-- Font scales smoothly 24px → 48px -->
/* Heading that scales with page -->
h1 {
font-size: clamp(32px, 8vw, 64px);
/* Large: 32px minimum, 64px maximum -->
}
h2 {
font-size: clamp(24px, 5vw, 40px);
}
h3 {
font-size: clamp(20px, 4vw, 32px);
}
/* Body text stays readable -->
p {
font-size: clamp(14px, 2.5vw, 18px);
/* Small phones: 14px, large screens: 18px -->
}
<!-- All text scales proportionally with viewport -->
/* Without clamp: requires media queries -->
h1 {
font-size: 32px;
}
@media (min-width: 768px) {
h1 { font-size: 48px; }
}
@media (min-width: 1024px) {
h1 { font-size: 64px; }
}
<!-- More verbose, less smooth -->
<!-- With clamp: smooth, elegant, no breakpoints -->clamp() syntax and values
Parameter | Purpose | Example |
|---|---|---|
min | Smallest size | 16px |
preferred | Scales with viewport | 5vw (5% viewport width) |
max | Largest size | 32px |
CSS
<!-- Different viewport-relative units -->
/* vw: viewport width percentage -->
.element {
font-size: clamp(16px, 2.5vw, 24px);
/* 2.5% of viewport width, between 16-24px -->
}
/* vh: viewport height percentage -->
.element {
font-size: clamp(16px, 3vh, 24px);
/* 3% of viewport height, between 16-24px -->
}
/* em/rem: relative to font size -->
.element {
font-size: clamp(1rem, 5vw, 3rem);
/* Between 1rem and 3rem, scaling 5vw -->
}
/* Practical readable range -->
body {
font-size: clamp(14px, 2.5vw, 20px);
/* Body text: 14px (phone) to 20px (desktop) -->
}
h1 {
font-size: clamp(28px, 6vw, 48px);
/* Heading: 28px (phone) to 48px (desktop) -->
}
.caption {
font-size: clamp(12px, 1.5vw, 16px);
/* Caption: 12px (phone) to 16px (desktop) -->
}Practical fluid typography patterns
CSS
<!-- Responsive heading hierarchy -->
h1 {
font-size: clamp(32px, 8vw, 64px);
margin: clamp(20px, 5vw, 40px) 0;
}
h2 {
font-size: clamp(24px, 5vw, 40px);
margin: clamp(16px, 4vw, 28px) 0;
}
h3 {
font-size: clamp(20px, 3.5vw, 28px);
margin: clamp(12px, 2vw, 20px) 0;
}
body {
font-size: clamp(14px, 2.5vw, 18px);
line-height: clamp(1.4, 2vw, 1.8);
}
<!-- Everything scales proportionally -->
/* Readable column width with fluid text -->
.container {
max-width: 800px;
margin: 0 auto;
padding: clamp(16px, 5vw, 40px);
}
.container h1 {
font-size: clamp(32px, 5vw, 48px);
}
.container p {
font-size: clamp(14px, 2vw, 18px);
line-height: 1.6;
}
<!-- Text and container grow together -->
/* Heading with line height scaling -->
h1 {
font-size: clamp(32px, 8vw, 56px);
line-height: clamp(1.1, 1.5vw, 1.4);
/* Line height also scales for readability -->
}
<!-- Better readability: more spacing on larger screens -->
/* Letter spacing for titles -->
.hero-title {
font-size: clamp(36px, 10vw, 72px);
letter-spacing: clamp(-0.02em, 1vw, 0.1em);
/* Tighter on small screens, looser on large -->
}
<!-- Proportional letter spacing -->Advanced fluid typography
CSS
<!-- Combining with CSS variables -->
:root {
--text-min: 14px;
--text-max: 18px;
--text-preferred: 2.5vw;
--heading-min: 28px;
--heading-max: 48px;
--heading-preferred: 6vw;
}
body {
font-size: clamp(var(--text-min), var(--text-preferred), var(--text-max));
}
h1 {
font-size: clamp(var(--heading-min), var(--heading-preferred), var(--heading-max));
}
<!-- Centralized fluid sizing values -->
/* Fluid spacing using same ratios -->
.container {
padding: clamp(16px, 5vw, 40px);
gap: clamp(12px, 3vw, 24px);
}
<!-- Consistent scaling -->
/* Mobile-first base with fluid scaling -->
html {
font-size: 16px; /* base -->
}
h1 {
font-size: clamp(1.75rem, 8vw, 3.5rem);
/* Scales from 28px (1.75 × 16) to 56px (3.5 × 16) -->
}
body {
font-size: clamp(0.875rem, 2.5vw, 1.125rem);
/* Base text 14px to 18px -->
}
<!-- Maintains 16px base while allowing scale -->
/* Preventing too-small text on narrow screens -->
.element {
font-size: clamp(16px, 4vw, 24px);
/* Never smaller than 16px, even on very narrow screens -->
}
/* Accessible minimum text size -->
body {
font-size: clamp(16px, 2vw, 20px);
/* Minimum 16px for accessibility -->
}
<!-- Always readable, scales up with space -->
/* Testing fluid typography -->
/* At 320px width: 320 × 2.5vw = 8px scale + 14px min = 14px -->
/* At 1024px width: 1024 × 2.5vw = 25.6px, clamped to 18px max = 18px -->
/* At 1920px width: 1920 × 2.5vw = 48px, clamped to 18px max = 18px -->Browser support and fallbacks
CSS
<!-- clamp() supported in modern browsers -->
/* Chrome 79+, Firefox 75+, Safari 13.1+, Edge 79+ */
.heading {
font-size: clamp(24px, 5vw, 48px);
}
<!-- Wide support in modern browsers -->
/* Fallback for older browsers -->
.heading {
font-size: 24px; /* fallback: minimum size -->
}
@supports (font-size: clamp(1px, 1vw, 1px)) {
.heading {
font-size: clamp(24px, 5vw, 48px);
}
}
<!-- Uses fallback in unsupported browsers -->
/* Media query fallback approach -->
.heading {
font-size: 24px; /* mobile -->
}
@media (min-width: 768px) {
.heading {
font-size: 32px; /* tablet -->
}
}
@media (min-width: 1024px) {
.heading {
font-size: 48px; /* desktop -->
}
}
@supports (font-size: clamp(1px, 1vw, 1px)) {
.heading {
font-size: clamp(24px, 5vw, 48px); /* fluid if supported -->
}
}
<!-- Best of both worlds: clamp with media query fallback -->Note
Fluid typography using `clamp(min, preferred, max)` scales smoothly with viewport width without media queries. Use `vw` (viewport width) for the preferred value to scale proportionally. Combine with proportional margins, padding, and line-height for harmonious scaling across all screen sizes.
Next
Responsive images: [Responsive Images](/css/responsive-images).