Get the Balance Right: Responsive Display Text
Last year in 24 ways I urged you to Get Expressive with Your Typography. I made the case for grabbing your readers’ attention by setting text at display sizes, that is to say big. You should consider very large text in the same way you might a hero image: a picture that creates an atmosphere and anchors your layout.
When setting text to be read, it is best practice to choose body and subheading sizes from a pre-defined scale appropriate to the viewport dimensions. We set those sizes using rems
, locking the text sizes together so they all scale according to the page default and your reader’s preferences. You can take the same approach with display text by choosing larger sizes from the same scale.
However, display text, as defined by its purpose and relative size, is text to be seen first, and read second. In other words a picture of text. When it comes to pictures, you are likely to scale all scene-setting imagery - cover photos, hero images, and so on - relative to the viewport. Take the same approach with display text: lock the size and shape of the text to the screen or browser window.
Introducing viewport units
With CSS3 came a new set of units which are locked to the viewport. You can use these viewport units wherever you might otherwise use any other unit of length such as pixels, ems
or percentage. There are four viewport units, and in each case a value of 1
is equal to 1% of either the viewport width or height as reported in reference1 pixels:
vw
- viewport width,vh
- viewport height,vmin
- viewport height or width, whichever is smallervmax
- viewport height or width, whichever is larger
In one fell swoop you can set the size of a display heading to be proportional to the screen or browser width, rather than choosing from a scale in a series of media queries. The following makes the heading font size 13% of the viewport width:
h1 {
font-size: 13 vw;
}
So for a selection of widths, the rendered font size would be:
Viewport width | 13 vw |
---|---|
320 | 42 |
768 | 100 |
1024 | 133 |
1280 | 166 |
1920 | 250 |
A problem with using vw
in this manner is the difference in text block proportions between portrait and landscape devices. Because the font size is based on the viewport width, the text on a landscape display is far bigger than when rendered on the same device held in a portrait orientation.
The proportions of the display text relative to the screen are so dissimilar that each orientation has its own different character, losing the inconsistency and considered design you would want when designing to make an impression.
However if the text was the same size in both orientations, the visual effect would be much more consistent. This where vmin
comes into its own. Set the font size using vmin
and the size is now set as a proportion of the smallest side of the viewport, giving you a far more consistent rendering.
h1 {
font-size: 13vmin;
}
Comparing vw
and vmin
renderings for various common screen dimensions, you can see how using vmin
keeps the text size down to a usable magnitude:
Viewport | 13 vw | 13 vmin |
---|---|---|
320 × 480 | 42 | 42 |
414 × 736 | 54 | 54 |
768 × 1024 | 100 | 100 |
1024 × 768 | 133 | 100 |
1280 × 720 | 166 | 94 |
1366 × 768 | 178 | 100 |
1440 × 900 | 187 | 117 |
1680 × 1050 | 218 | 137 |
1920 × 1080 | 250 | 140 |
2560 × 1440 | 333 | 187 |
Hybrid font sizing
Using vertical media queries to set text in direct proportion to screen dimensions works well when sizing display text. In can be less desirable when sizing supporting text such as sub-headings, which you may not want to scale upwards at the same rate as the display text. For example, we can size a subheading using vmin
so that it starts at 16 px on smaller screens and scales up in the same way as the main heading:
h1 {
font-size: 13vmin;
}
h2 {
font-size: 5vmin;
}
The balance of display text to supporting text on the phone works well, but the subheading text on the tablet, even though it has been increased in line with the main heading, is starting to feel disproportionately large and a little clumsy. This problem becomes magnified on even bigger screens.
A solution to this is use a hybrid method of sizing text2. We can use the CSS calc()
function to calculate a font size simultaneously based on both rems
and viewport units. For example:
h2 {
font-size: calc(0.5rem + 2.5vmin);
}
For a 320 px wide screen, the font size will be 16 px, calculated as follows:
(0.5 × 16) + (320 × 0.025) = 8 + 8 = 16px
For a 768 px wide screen, the font size will be 27 px:
(0.5 × 16) + (768 × 0.025) = 8 + 19 = 27px
This results in a more balanced subheading that doesn’t take emphasis away from the main heading:
To give you an idea of the effect of using a hybrid approach, here’s a side-by-side comparison of hybrid and viewport text sizing:
16 | 20 | 27 | 32 | 35 | 40 | 44 |
16 | 24 | 38 | 48 | 54 | 64 | 72 |
320 | 480 | 768 | 960 | 1080 | 1280 | 1440 |
Over this festive period, try experiment with the proportion of rem
and vmin
in your hybrid calculation to see what feels best for your particular setting.
-
A reference pixel is based on the logical resolution of a device which takes into account double density screens such as Retina displays. ↩︎
-
For even more sophisticated uses of hybrid text sizing see the work of Mike Riethmuller. ↩︎
About the author
Richard Rutter is a user experience consultant and director of Clearleft. In 2009 he cofounded the webfont service, Fontdeck. He runs an ongoing project called The Elements of Typographic Style Applied to the Web, where he extols the virtues of good web typography. Richard occasionally blogs at Clagnut, where he writes about design, accessibility and web standards issues, as well as his passion for music and mountain biking.