Fluid typography
And, font-size: calc(vw + em)
If you are a web developer, you’ve probably seen font-size declarations something like this:
body {
font-size: calc(21px + 3 * ((100vw - 375px) / 825));
}
But back in 2017, I saw an unusual font-size declaration for the first time:
body {
font-size: calc(1.9393939394vw + 2.8727272727em);
}
The calculation seemed like magic, leaving me scratching my head. I had no idea how it worked or how it was calculated. I searched online but couldn’t find any answers. Still, I had to figure it out myself. It seemed pretty cool to explore.
In 2024, the frustration grew as I continued to work with fluid font sizes. But I remain hopeful that one day, I’ll unlock its logic, inshallah.
I know the fundamental
Here’s the math, credit Mike Riethmuller:
body {
font-size: calc(min_font + (max_font - min_font) * ((100vw - min_viewport_width) / (max_viewport_width - min_viewport_width)));
}
This is a simplified version of fluid font size with pixels.
If I want the font size to range from 21px
on a 375px
screen to 24px
on a 1200px
screen, it would be like this:
body {
font-size: 21px;
font-size: calc(21px + (24 - 21) * ((100vw - 375px) / (1200 - 375)));
}
@media screen and (min-width: 1200px) {
body {
font-size: 24px;
}
}
Browsers will render the calc()
function as follows:
body {
font-size: calc(21px + 3 * (100vw - 375px) / 825);
}
This isn’t what I want.
I want to render something like this:
body {
font-size: calc(0.3636363636vw + 19.6363636364px);
}
So, I need to do some basic math. But it took me 7 years to figure it out. Here’s an example:
// math
1: 21px + (24 - 21) * ((100vw - 375px) / (1200 - 375))
2: 21px + (24 - 21) * ((100vw / (1200 - 375)) - (375px / (1200 - 375)))
3: 21px + ((24 - 21) * (100vw / (1200 - 375))) - ((24 - 21) * (375px / (1200 - 375)))
4: ((24 - 21) * (100vw / (1200 - 375))) + (21px - ((24 - 21) * (375px / (1200 - 375))))
// browser will render
1: 21px + 3 * (100vw - 375px) / 825
2: 21px + 3 * (0.1212121212vw - 0.4545454545px)
3: 21px + 0.3636363636vw - 1.3636363636px
4: 0.3636363636vw + 19.6363636364px
Last one is the output I want. So here’s the final math:
body {
font-size: calc(((max_font - min_font) * 100vw / (max_viewport_width - min_viewport_width)) + (min_font - ((max_font - min_font) * min_viewport_width) / (max_viewport_width - min_viewport_width)));
}
In Sass
I love Sass, and Dart Sass is my go-to for every project.
When it comes to units, I prefer em
. Remember, 1em = 16px
. To keep things simple, I start by setting the body font-size to 62.5%
, making 1em = 10px
.
body
font-size: 62.5%
Finally I’ve crafted a (pretty robust) @mixin, like this:
// Fluid Font Size (ffs)
// target: calc(vw + em)
@use "sass:math"
@function strip-unit($value)
@return math.div($value, ($value * 0 + 1))
=ffs($fs-max, $fs-min, $w-max: strip-unit($w-max), $w-min: strip-unit($w-min))
font-size: calc(($fs-max - $fs-min) * 100vw / ($w-max - $w-min) + (($fs-min * .1em) - ($fs-max - $fs-min) * ($w-min * .1em) / ($w-max - $w-min)))
Here’s how I use it:
$w-min: 375px
$w-max: 1200px
p
+ffs(24, 21)
Now, the browser renders my desired target:
p {
font-size: calc(0.3636363636vw + 1.9636363636em);
}
Conclusion
Yes, after 7 long years, I’ve finally cracked its logic. Alhamdulillah.
Am I leaving you scratching your head?
I understand it’s tough. Fluid font sizes, result like calc(vw + em)
,
might seem tricky initially, but with the right approach,
you’ll get there too. Read well, be patient. Best of luck!
Zafree, available for hire
Hire meRead more
React Locally
I create my own react starter kit. Why I use it, what’s in it and what’s not.
- React
PMI Bangladesh
A meetup landing page proposal
- Design
- Proposal
Pilpil.js
A tiny JavaScript library for Progressive Image Loading.
- JavaScript
PayPal Fun
How I Welcome PayPal in Bangladesh.
- CSS
- JavaScript
CSS Zen Garden
A friendly CSS design challenge by recruiter before hiring me.
- Design
BUBT Professional Meetup
It’s the “Meetup” we all BUBTians wanted to attend.
- Community
- Design
- Development
Lets guess!
Which one is image and which one build with CSS?
- CSS
Sticky-kit problem
There is a problem in sticky-kit with bootstrap. I fixed it.
- JavaScript