💡 This post has an update: "Easy Fluid Typography"
The principles that govern typographic design on the printed page don't always transfer to the digital screen. In web development, we don't need to worry about maximizing words per page or minimizing the total page count. The economies of the printed page aren't relevant on the web. For digital developers and designers, the possibilities are nearly endless.
And therein lies the problem. Our vast range of possibilities is also available to our readers (like you, right now), who can read text on a smartphone, tablet, laptop, or an ultrawide 8K display in a vertical orientation. Whereas the printed page is invariably defined (text is typeset after all), the digital viewport is a shapeshifting specter, forever haunting our designs.
How do you ensure that your text is comfortable to read on any viewport?
Thankfully, solutions exist to scale the font size of your design in relation to changes in viewport size (and I'm indebted here to posts on the subject by Geoff Graham and Michael Riethmuller). Generally speaking (and perhaps counterintuitively), font size should increase as the viewport increases, since there is more room on larger screens, and the user is likely sitting further away from it, compared to a phone.
Below I offer three solutions. Though each accomplishes the goal of increasing font size based on the viewport width, I recommend the third option as being the best (it's also implemented on this website):
- Responsive Typography (easiest to get up and running)
- Fluid Typography (implements continuous font-size scaling)
- Fluid Typography via SASS mixin (easiest implementation for fluid scaling)
- Fluid Typography via JavaScript (accessibility-friendly solution)
Responsive Typography
Responsive typography, which defines different font sizes based on media queries, is the easiest solution to implement and has the widest browser support. First, define your minimum desired font size (16px recommended) via CSS on your html
selector. Then, increase your font size for each media query breakpoint. See the example below for an illustration.
By altering the root font size, we can use the rem
CSS unit to alter the size of other typographic elements. For example, for an H1
tag with a size of 2.5rem, it would have the following sizes according to the CSS rules above.
Viewport Width | < 640 px | > 639px | > 1023px | > 1279px |
---|---|---|---|---|
Base Font Size | 16px | 17px | 18px | 19px |
H1 Font Size | 40px | 42.5px | 45px | 47.5px |
Fluid Typography
Fluid typography expands on responsive typography by implementing a formula to scale text in relation to the size of the viewport. Rather than changing font size in discrete steps according to media query breakpoints, as seen above, fluid typography sets font size along a continuum in relation to the width of the viewport.
To achieve this result, it is necessary to define a formula in CSS that is capable of dynamically updating the font-size
property. The key to this formula is the CSS unit "vw" or viewport width.
The formula is as follows: min font size + (max font size - min font size) * (100vw - min vw) / (max vw - min vw)
For example, given the following arguments of 16px min font size, 23px max font size, 640px min vw, and 1440px max vw; the formula would yield the following results:
Viewport Width | Base Font Size |
---|---|
< 640px | 16px |
700px | 16.5167px |
750px | 16.95px |
1200px | 20.9px |
> 1440px | 23px |
To implement the formula in CSS, you'd write the following rules:
Fluid Typography via SASS Mixin
If you're using SASS/SCSS, you can implement the above solution using a mixin. The advantage of using a mixin is the ability to update variables easily and to generate the media query breakpoints automatically. The mixin and its use are shown below.
👉 See it in action. Remember to resize the browser to see the effect.
Fluid Typography via JavaScript
The previous solution is limited in terms of accessibility since setting font size in pixels will overwrite user-defined values. For example, if a user has set the font size in the browser to be 22px, the above solution would overwrite that value with 16px, which is undesirable.
Unfortunately, the way calc
works in CSS doesn't allow for using a rem-based solution. You could use the responsive solution, the first example above, but then you lose fluidity. With JavaScript, though, you can preserve font-size fluidity, user-defined preferences, and aspects of your design.
The constructor defined below works by taking four arguments, the same as those above. Then, if the user has not set a font-size preference, it implements those sizes on the DOM. If the user has set a preference, then the function implements the same ratio you defined between the smallest and largest font sizes. For example, if you defined your smallest font size as 16px and the largest as 23px, then that represents a 43.75% increase. If a user defines a minimum font size of 22px, then the function will calculate the rem of the page based on the user-supplied minimum and a 43.75% increase. For 22px, that would mean a maximum of 31.625px. The function is below.
👉 See it in action. Remember to resize the browser to see changes.