16 February 2021
Fluid Typography, Simplified
Along with responsive design came responsive typography, and now quickly on the rise is the concept of fluid typography. When I first started hearing the term “fluid typography,” my immediate thought was, “What’s that?” So for anyone wondering the same thing, here’s a quick definition:
Fluid typography is the idea that font-size and line-height respond smoothly to viewport size changes, as opposed to responding at specific media query breakpoints.
Now, there are several ways to go about setting up fluid typography for your design system, and they all work. But, (to me) they’ve all felt a little hand-wavey and I haven’t understood what’s making them work behind the scenes, which just leads to me copy + pasting and backing away slowly. That is, until recently with the rollout of the CSS function clamp()
! The clamp()
function reduces both the number of lines and the complexity of the code you need for smooth responsive typography.
Simple setup
So, to set this up successfully, we’ll want to give the font-size a variable size relative to the viewport size—think vw
and vh
. But what has made this tricky in the past is that we also want to set a min and max font-size, otherwise our content will become unreadable at really small or really large screen widths. That’s why clamp()
fits perfectly! When using clamp()
you set a minimum, variable, and maximum value for the font-size with one line of code.
So we set up our root and header font-sizes something like this:
body {
font-size: clamp(16px, 2.5vw, 18px);
}
h1 {
font-size: clamp(1.75rem, 5vw, 2.5rem);
}
h2 {
font-size: clamp(1.5rem, 4vw, 2rem);
}
h3 {
font-size: clamp(1.2rem, 3.5vw, 1.75rem);
}
h4 {
font-size: clamp(1.1rem, 3vw, 1.5rem);
}
h5 {
font-size: clamp(1rem, 2.5vw, 1.2rem);
}
A little fancier now
Now, this is great because our typography can now respond to every single screen width—but notice I said screen width. After getting the above up and working, I wanted to see if I could find a way to set up my design system to adjust to all screen sizes, even wide and short viewports. That’s when I discovered a little thing called vmin
. Where the vw
unit is equal to 1% of the viewport width and the vh
unit is equal to 1% of the viewport height, vmin
is equal to 1% of the viewport’s smaller dimension. All that to say, there is a unit that takes into account both viewport height and width, therefore would account for wide, short viewports, too!
So just swap out vw
for vmin
in the code we wrote above, and then play with the browser size. I had way too much fun with that.
body {
font-size: clamp(16px, 2.5vmin, 18px);
}
[…]
Browser support
Luckily, both clamp()
and vmin
are pretty widely supported, so there’s not much we need to do in addition to the above code. The one exception there is Internet Explorer, likely to no one’s surprise. It doesn’t support clamp()
—but that’s our only sticking point. So to remedy that, we can simply add a fallback font-size declaration on the line above our clamp()
style (you know, follow the cascade), like this:
body {
font-size: 18px;
font-size: clamp(16px, 2.5vmin, 18px);
}
h1 {
font-size: 2.5rem;
font-size: clamp(1.75rem, 5vmin, 2.5rem);
}
h2 {
font-size: 2rem;
font-size: clamp(1.5rem, 4vmin, 2rem);
}
h3 {
font-size: 1.75rem;
font-size: clamp(1.2rem, 3.5vmin, 1.75rem);
}
h4 {
font-size: 1.5rem;
font-size: clamp(1.1rem, 3vmin, 1.5rem);
}
h5 {
font-size: 1.2rem;
font-size: clamp(1rem, 2.5vmin, 1.2rem);
}
And wa-lah! There you have it. Two lines of code and you’ve got super slick typography, browser support, and a fallback! I like to use the same method for line-height in my design system, but I like to use a SASS mixin I built called grid()
as my min and max values in the clamp()
to maintain a vertical grid. For more on that, check out this other article on setting up a vertical grid.
I’m currently playing with expanding this concept past typography into other areas of my design system—think padding, margins, widths, etc. so that the entire interface scales smoothly with viewport changes. We’ll see how it goes, more to come on that later!
Want to see it in action? Check out this codepen demo.