Flexible Typography (clamp(), min(), max())
Flexible typography in CSS allows you to create fluid and responsive text that adapts to different screen sizes. By using the clamp()
, min()
, and max()
functions, you can set a font size that grows or shrinks with the viewport, but doesn't go below a minimum size or above a maximum size. This ensures your text is always readable and well-proportioned, improving the user experience on any device.
clamp()
The clamp()
function takes three values: a minimum value, a preferred value, and a maximum value. It allows you to set a font size that smoothly scales between the minimum and maximum based on the preferred value, which is often a viewport-dependent unit like vw
.
Example 1: Basic Clamp
/* This example sets a font size for the h1 element. */
h1 {
/*
The font size will be at least 2rem, at most 4rem,
and will try to be 5vw.
*/
font-size: clamp(2rem, 5vw, 4rem);
}
Explanation
The h1
element's font size is instructed to be 5vw
(5% of the viewport width). However, it will not shrink below 2rem
on smaller screens or grow larger than 4rem
on very wide screens, ensuring readability and preventing overly large text.
Example 2: Clamp for Paragraphs
/* This example applies clamp() to a paragraph for readable body text. */
p {
/*
The font size is constrained between 1rem and 1.2rem,
with a preferred size of 1vw + 0.8rem.
*/
font-size: clamp(1rem, 1vw + 0.8rem, 1.2rem);
}
Explanation
This code sets a base font size of 0.8rem
and adds 1vw
to it, allowing the paragraph text to scale with the viewport. The clamp()
function ensures the font size never falls below 1rem
or exceeds 1.2rem
, maintaining optimal readability for body copy.
Example 3: Clamp with Different Units
/* This example demonstrates using different units within clamp(). */
.title {
/*
The font size is clamped between 24px and 48px,
with a preferred size of 4vw.
*/
font-size: clamp(24px, 4vw, 48px);
}
Explanation
Here, we use pixels for the minimum and maximum values and a viewport width unit for the preferred value. This is a common and practical approach for controlling font size scaling in a pixel-perfect design system.
Example 4: Clamp for Responsive Headings
/* This example shows clamp() on a secondary heading. */
h2 {
/*
The h2 will have a minimum font size of 1.5rem, a maximum of 3rem,
and a preferred size of 4vw + 1rem.
*/
font-size: clamp(1.5rem, 4vw + 1rem, 3rem);
}
Explanation
This h2
heading scales more dramatically than a paragraph. The combination of 4vw + 1rem
allows for a more significant change in font size across different screen sizes, while clamp()
keeps it within a reasonable range.
Example 5: Clamp in a Card Component
/* This example uses clamp() within a card component. */
.card-title {
/*
The card title's font size is clamped between 1.25rem and 1.75rem,
with a preferred size of 2vw + 0.5rem.
*/
font-size: clamp(1.25rem, 2vw + 0.5rem, 1.75rem);
}
Explanation
In this scenario, the .card-title
font size adjusts based on the viewport width, but its scaling is contained within a narrow range (1.25rem
to 1.75rem
). This is ideal for components where you need subtle responsiveness without drastic changes.
min()
The min()
function takes one or more comma-separated values and applies the smallest of them. For flexible typography, it's useful for setting a font size that scales down with the viewport but doesn't exceed a specific maximum size.
Example 1: Basic min()
/* This example uses min() to set a maximum font size. */
h1 {
/*
The font size will be the smaller of 10vw or 4rem.
*/
font-size: min(10vw, 4rem);
}
Explanation
The h1
font size is set to 10vw
, so it scales with the viewport. However, if 10vw
becomes larger than 4rem
, the font size will be capped at 4rem
, preventing it from becoming excessively large on wide screens.
Example 2: min() for UI Elements
/* This example applies min() to a button's font size. */
.button {
/*
The font size is the smaller of 4vw or 1.2rem.
*/
font-size: min(4vw, 1.2rem);
}
Explanation
This ensures the button text scales on smaller screens but never exceeds 1.2rem
. This is useful for maintaining a consistent UI and preventing buttons from becoming too large in a desktop layout.
Example 3: min() with Calculations
/* This example uses a calculation within min(). */
.subtitle {
/*
The font size will be the smaller of 3vw + 1rem or 2.5rem.
*/
font-size: min(3vw + 1rem, 2.5rem);
}
Explanation
The preferred font size is a combination of a viewport unit and a fixed unit. The min()
function acts as a ceiling, ensuring that no matter how wide the viewport is, the font size for .subtitle
will not go beyond 2.5rem
.
Example 4: min() for Constraining Text
/* This example uses min() to constrain paragraph text. */
p {
/*
The font size is the smaller of 2vw or 1rem.
*/
font-size: min(2vw, 1rem);
}
Explanation
Here, the paragraph font size will be 2vw
, making it responsive on smaller devices. However, on larger screens where 2vw
would be greater than 1rem
, the font size is capped at 1rem
to maintain a comfortable reading size.
Example 5: min() in a Header
/* This example uses min() for a navigation link in a header. */
.nav-link {
/*
The font size will be the smaller of 3.5vw or 1.1rem.
*/
font-size: min(3.5vw, 1.1rem);
}
Explanation
The .nav-link
font size will shrink for smaller viewports but will stop growing once it reaches 1.1rem
. This provides a fluid experience on mobile while maintaining a clean and appropriately sized navigation on desktop.
max()
The max()
function takes one or more comma-separated values and applies the largest of them. It's useful for setting a font size that scales up with the viewport but doesn't go below a specific minimum size, ensuring readability on small screens.
Example 1: Basic max()
/* This example uses max() to set a minimum font size. */
h1 {
/*
The font size will be the larger of 5vw or 2rem.
*/
font-size: max(5vw, 2rem);
}
Explanation
The h1
font size is set to 5vw
, allowing it to scale with the viewport. If 5vw
becomes smaller than 2rem
, the font size will be floored at 2rem
. This guarantees a minimum readable size on small devices.
Example 2: max() for Body Text
/* This example applies max() to paragraph text. */
p {
/*
The font size is the larger of 1vw or 1rem.
*/
font-size: max(1vw, 1rem);
}
Explanation
This ensures that the paragraph text is never smaller than 1rem
. On larger screens, the font size will grow with the viewport (1vw
), providing a more dynamic reading experience.
Example 3: max() with Calculations
/* This example uses a calculation within max(). */
.highlight {
/*
The font size is the larger of 2vw + 0.5rem or 1.5rem.
*/
font-size: max(2vw + 0.5rem, 1.5rem);
}
Explanation
The font size for .highlight
is intended to be responsive (2vw + 0.5rem
). The max()
function establishes a minimum size of 1.5rem
, preventing the text from becoming too small and unreadable on narrow viewports.
Example 4: max() for Call-to-Action Text
/* This example uses max() for a prominent call-to-action. */
.cta-text {
/*
The font size will be the larger of 6vw or 1.75rem.
*/
font-size: max(6vw, 1.75rem);
}
Explanation
The .cta-text
is designed to be large and attention-grabbing. By using max()
, its font size scales with the viewport (6vw
) but will never be smaller than 1.75rem
, ensuring its impact is not lost on mobile devices.
Example 5: max() in a Footer
/* This example uses max() for footer text. */
.footer-text {
/*
The font size will be the larger of 0.8vw or 0.9rem.
*/
font-size: max(0.8vw, 0.9rem);
}
Explanation
Footer text is often smaller, but it still needs to be readable. This code ensures the .footer-text
font size never drops below 0.9rem
, while allowing it to scale subtly (0.8vw
) on larger screens.