Easily manage projects with monday.com
Fluid typography is the idea that font-size
(and perhaps other attributes of type, like line-height
) change depending on the screen size (or perhaps container queries if we had them).
The core trickery comes from viewport units. You can literally set type in viewport units (e.g. font-size: 4vw
), but the fluctuations in size are so extreme that it's usually undesirable. That's tampered by doing something like font-size: calc(16px + 1vw)
. But while we're getting fancy with calculations anyway, the most common implementation ended up being an equation to calculate plain English:
I want the type to go between being 16px on a 320px screen to 22px on a 1000px screen.
Which ended up like this:
html {
font-size: 16px;
}
@media screen and (min-width: 320px) {
html {
font-size: calc(16px + 6 * ((100vw - 320px) / 680));
}
}
@media screen and (min-width: 1000px) {
html {
font-size: 22px;
}
}
That's essentially setting a minimum and maximum font size so the type won't shrink or grow to anything too extreme. "CSS locks" was a term coined by Tim Brown.
Minimum and maximum you say?! Well it so happens that functions for these have made their way into the CSS spec in the form of min()
and max()
.
So we can simplify our fancy setup above with a one-liner and maintain the locks:
html {
font-size: min(max(16px, 4vw), 22px);
}
We actually might want to stop there because even though both Safari (11.1+) and Chrome (79+) support this at the current moment, that's as wide as support will get today. Speaking of which, you'd probably want to slip a font-size
declaration before this to set an acceptable fallback value with no fancy functions.
But as long as we're pushing the limits, there is another function to simplify things even more: clamp()
! Clamp takes three values, a min, max, and a flexible unit (or calculation or whatever) in the middle that it will use in case the value is between the min and max. So, our one-liner gets even smaller:
body {
font-size: clamp(16px, 4vw, 22px);
}
That'll be Chrome 79+ (which doesn't hasn't shipped to stable but will very soon).
Uncle Dave is very happy that FitText is now a few bytes instead of all-of-jQuery plus 40 more lines. Here is Dave chucking CSS custom properties at it:
See the Pen
FitText in CSS with clamp() by Dave Rupert (@davatron5000)
on CodePen.
Brilliant! Please someone make a poly fill for the clamp trick in ES6.
But 4vw gets you to 22px at a screen width of only 550px, so you’re better off with the calculation.
@Matt, ain’t that the point, or isn’t this intended?
Font size is 4vw up to 550px screen width. Everything up is limited to 22px.
Agreed, I prefer being able to define when the scaling should end using viewport width, which the long
calc()
formula lets you do. I created a custom Sass mixin to make it easier to generate those formulas https://threespot.github.io/frontline-sass/documentation/#main-function-fs-scale Hope others find it useful!This is a great tip/trick. It can really save some headache on making my website mobile-friendly. Thank you!
Good stuff there
I wonder what this means for using rem units in a project? If you’re using fluid type then I would think all your other elements should be sized using PX. Otherwise, if the user changes the base font size then all the elements will scale up except the text.
Does this still work properly if the user browser’s default font size is outside that min-max range? I have mine set at 24 px because my eyes are terrible.
I wonder what you think about the use of ch units. They are fairly well supported plus, although they are not perfect, they are quite good to cope with situations in which we want to keep the number of characters per line within a reasonable range in paragraphs. Also we could fine tune them using formulas (calc())
That’s pretty neat. I’ve been doing something similar using a scss mixin and it has worked out very good so far.
See the Pen Fluid Typography by Marc Müller
(@mkmueller) on CodePen.
RFS is a great example as well. It supports responsive sizing of other CSS properties now too and is part of Bootstrap: https://github.com/twbs/rfs