CSS Weekly #9: Responsive Typography with clamp()
CSS Weekly #9: Responsive Typography with clamp() 📏
Hey ,
Let's master fluid, responsive typography using CSS clamp()! Say goodbye to media queries for font sizes.
Understanding clamp()
/* clamp(minimum, preferred, maximum) */
font-size: clamp(1rem, 2vw + 1rem, 3rem);
- Minimum: Never smaller than this
- Preferred: Flexible value (usually with viewport units)
- Maximum: Never larger than this
🎯 The Perfect Formula
My go-to responsive type scale:
:root {
/* Base values */
--fluid-min-width: 320;
--fluid-max-width: 1200;
/* Fluid type scale */
--step--2: clamp(0.69rem, calc(0.66rem + 0.18vw), 0.80rem);
--step--1: clamp(0.83rem, calc(0.78rem + 0.29vw), 1.00rem);
--step-0: clamp(1.00rem, calc(0.91rem + 0.43vw), 1.25rem);
--step-1: clamp(1.20rem, calc(1.07rem + 0.63vw), 1.56rem);
--step-2: clamp(1.44rem, calc(1.26rem + 0.89vw), 1.95rem);
--step-3: clamp(1.73rem, calc(1.48rem + 1.24vw), 2.44rem);
--step-4: clamp(2.07rem, calc(1.73rem + 1.70vw), 3.05rem);
--step-5: clamp(2.49rem, calc(2.03rem + 2.31vw), 3.82rem);
}
/* Usage */
h1 { font-size: var(--step-5); }
h2 { font-size: var(--step-4); }
h3 { font-size: var(--step-3); }
body { font-size: var(--step-0); }
small { font-size: var(--step--1); }
Real-World Examples
1. Article Typography
.article {
/* Optimal reading line length */
max-width: clamp(45ch, 50%, 75ch);
margin-inline: auto;
/* Fluid spacing */
padding: clamp(1rem, 5vw, 3rem);
}
.article h1 {
font-size: clamp(2rem, 5vw + 1rem, 4rem);
line-height: 1.1;
margin-bottom: clamp(1rem, 3vw, 2rem);
}
.article p {
font-size: clamp(1rem, 1vw + 0.9rem, 1.25rem);
line-height: clamp(1.5, 1vw + 1.5, 1.75);
margin-bottom: clamp(0.75rem, 2vw, 1.5rem);
}
.article blockquote {
font-size: clamp(1.1rem, 2vw + 0.5rem, 1.5rem);
padding-left: clamp(1rem, 3vw, 2rem);
}
2. Hero Section
.hero {
padding: clamp(3rem, 10vw, 8rem) clamp(1rem, 5vw, 4rem);
}
.hero-title {
/* Dramatic scaling */
font-size: clamp(2.5rem, 10vw, 8rem);
font-weight: 900;
line-height: 0.9;
}
.hero-subtitle {
font-size: clamp(1rem, 2vw + 0.5rem, 2rem);
opacity: 0.8;
}
🚀 Advanced Techniques
Viewport-Based Type Scaling
/* Calculate precise fluid values */
:root {
--fluid-bp: calc(
(100vw - 20rem) / (75 - 20)
);
}
h1 {
font-size: calc(2rem + 3 * var(--fluid-bp));
/* Clamp as fallback */
font-size: clamp(2rem, calc(2rem + 3 * var(--fluid-bp)), 5rem);
}
Responsive Line Height
p {
font-size: clamp(1rem, 1vw + 0.875rem, 1.25rem);
/* Line height that scales with font size */
line-height: clamp(
1.5, /* Minimum */
calc(1.5 + 0.5 * ((100vw - 20rem) / 60)), /* Fluid */
1.75 /* Maximum */
);
}
Container-Based Typography
/* With container queries */
.card {
container-type: inline-size;
}
.card h3 {
/* Use container units! */
font-size: clamp(1.25rem, 5cqi, 2rem);
}
.card p {
font-size: clamp(0.875rem, 2cqi + 0.5rem, 1.125rem);
}
📐 Spacing Scale
Match your spacing to your type scale:
:root {
/* Fluid spacing scale */
--space-3xs: clamp(0.25rem, calc(0.23rem + 0.11vw), 0.31rem);
--space-2xs: clamp(0.50rem, calc(0.46rem + 0.22vw), 0.63rem);
--space-xs: clamp(0.75rem, calc(0.68rem + 0.33vw), 0.94rem);
--space-s: clamp(1.00rem, calc(0.91rem + 0.43vw), 1.25rem);
--space-m: clamp(1.50rem, calc(1.37rem + 0.65vw), 1.88rem);
--space-l: clamp(2.00rem, calc(1.83rem + 0.87vw), 2.50rem);
--space-xl: clamp(3.00rem, calc(2.74rem + 1.30vw), 3.75rem);
--space-2xl: clamp(4.00rem, calc(3.65rem + 1.74vw), 5.00rem);
--space-3xl: clamp(6.00rem, calc(5.48rem + 2.61vw), 7.50rem);
/* One-up pairs */
--space-s-m: clamp(1.00rem, calc(0.74rem + 1.30vw), 1.88rem);
--space-m-l: clamp(1.50rem, calc(1.20rem + 1.52vw), 2.50rem);
}
Practical Tips
1. Test Your Scales
/* Debug mode to visualize scales */
.debug * {
outline: 1px solid red;
position: relative;
}
.debug *::before {
content: attr(data-size);
position: absolute;
top: 0;
right: 0;
font-size: 10px;
background: red;
color: white;
padding: 2px;
}
2. Fallbacks for Older Browsers
/* Progressive enhancement */
h1 {
font-size: 2rem; /* Fallback */
font-size: clamp(2rem, 5vw + 1rem, 4rem); /* Modern */
}
/* Feature query */
@supports (font-size: clamp(1rem, 2vw, 3rem)) {
h1 {
font-size: clamp(2rem, 5vw + 1rem, 4rem);
}
}
3. Accessible Scaling
/* Respect user preferences */
html {
font-size: clamp(
100%, /* Minimum: user default */
90% + 0.5vw, /* Preferred: slight scaling */
125% /* Maximum: 125% of user default */
);
}
🎨 Complete System
Here's a complete fluid typography system:
:root {
/* Type scale */
--text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
--text-sm: clamp(0.875rem, 0.8rem + 0.35vw, 1rem);
--text-base: clamp(1rem, 0.9rem + 0.5vw, 1.25rem);
--text-lg: clamp(1.125rem, 1rem + 0.625vw, 1.5rem);
--text-xl: clamp(1.25rem, 1.1rem + 0.75vw, 1.875rem);
--text-2xl: clamp(1.5rem, 1.25rem + 1.25vw, 2.25rem);
--text-3xl: clamp(1.875rem, 1.5rem + 1.875vw, 3rem);
--text-4xl: clamp(2.25rem, 1.75rem + 2.5vw, 3.75rem);
--text-5xl: clamp(3rem, 2rem + 5vw, 6rem);
/* Line heights */
--leading-tight: 1.2;
--leading-normal: 1.6;
--leading-relaxed: 1.75;
}
/* Usage */
.prose h1 {
font-size: var(--text-4xl);
line-height: var(--leading-tight);
}
.prose p {
font-size: var(--text-base);
line-height: var(--leading-normal);
}
Resources
Sponsored by FontPair - Find the perfect font combinations. CSS Weekly readers get lifetime access for $29!
Final issue next week: CSS-in-JS vs Utility-First CSS!
— Sarah from CSS Weekly
P.S. Show me your fluid type scales! What's your preferred clamp formula?
Don't miss what's next. Subscribe to CSS Weekly:
Add a comment: