Authored by Primate

A rather awesome, informative
and witty blog about all things web

Responsive Type, part 4: Responsive consistency

Four t's arranged in a rectangle, the fourth one highlighted.

So here we are. We’ve covered font selection, typographic scale and vertical rhythm, but a very important consideration still remains: achieving responsive consistency. Now, for something that really isn’t rocket science, consistency in responsive typography can be quite tedious. However, with the right approach you’ll find it an empowering experience.


Well placed breakpoints are the key to solid responsive typography, and the best way to define them is to consider typography across viewport sizes. It is commonly accepted that breakpoints are inserted when the layout breaks. In a type-centric context this is just another way of saying that breakpoints are inserted when the measure is wrong. If (or should I say when) the measure of your main content exceeds or falls short of the ideal character count (45-75), insert a breakpoint.

What changes you make at each breakpoint varies, of course. If a measure is too long on a wide viewport, you can increase the font-size, put a max-width on your wrapper or introduce multiple columns. If it’s too short (for example on a mobile viewport), try reducing the font-size or number of columns. As long as your line-height is unitless or declared in ems you should find that it automatically changes to suit.

Basing our breakpoints on ems is also a good idea, as it means that any change in global font size (for example if users zoom in or out) will adapt the layout to suit.

Declaring responsive attributes

Whether you prefer to work ‘mobile-first’ or ‘desktop-down’, chances are you’ll need to refine your typography at your breakpoints to make sure the measure and font-size suit the viewport, and to do this we use media queries.

This really isn’t that difficult, and without a pre-processor, your code may end up looking something like this:

.header_1 { font-size: 4em; }

@media all and (min-width: 80em) {
  .header_1 { font-size: 5em; }

@media all and (max-width: 65em) {
  .header_1 { font-size: 3em; }

@media all and (max-width: 40em) {
  .header_1 { font-size: 2em; }

Simple enough. (Particularly so as my example doesn’t include any other attributes like line-height etc.). Whilst writing the initial CSS in this way is easy, maintaining it requires a steady head. If you want to retain a proportionate scaling of your heading at every breakpoint, you need to re-calculate the em values and update it in each and every media query. The same goes for the media queries themselves; if you were to tweak them half way through your build you’d have to make sure you updated the em value in every single query across your document.

It isn’t hard to see how inconsistencies could arise quickly in such a system.

Using Sass

If you use pre-processors however (in our case SASS), things are more easily maintained. It does require a little more work up front, but once the core variables, mixins, and functions have been defined, everything that follows is a breeze. Here’s one way of using SASS to keep things cleaner:

First, we define our media queries globally using variables. This way, queries are easily tweaked and only need to be updated in one place:

$wide: 80em;
$medium: 65em;
$small: 40em;

Next, we create a map which contains the typographic style definitions. The map includes the default `font-size` and `line-height`, and also the `font-size` and `line-height` at different breakpoints.

$header_1: (
  name: 'header_1',
  size_px: 50, line_height_baseline: 5, margin_bottom_baseline: 0,
  color: black, font_antialiased: true,
  breakpoints: (
    ($normal 40 4),
    ($small 30 3)

As mentioned previsously, we want to declare everything using ems, however I personally find it easier to work with pixels, which I also use in Photoshop/Illustrator. The pixel value will later be converted to ems at compilation time. If you are interested, the function used to convert the pixel value to ems is really simple:

$base_font_size_px: 16; // The base font size is almost always 16px.
@function px2em ($px) {
  @return ($px / $base_font_size_px) * 1em;

Line-height is defined as a multiplier of a baseline value, which on most of our projects ranges from between 8 to 12 px, and which is later converted to ems of course.

Breakpoints are defined, and for each breakpoint we specify the font-size (in pixels), and the line-height (in baseline multipliers). The example above has the following breakpoint definitions:

breakpoints: (
  ($medium 40 4),
  ($small 30 3)

This example is based on a desktop-first site, so the desktop styles are the default. Style changes are made as the screen width reduces, so at the `$medium` breakpoint the header font-size is reduced to 40px, and the line-height is reduced to 4 multipliers of the baseline. On a mobile-first site, the default styles would be defined for small screen widths, and breakpoints would be added to capture the screen width increasing.

I’ve glossed over a lot of the implementation here, but if you would like to find out more about how we implement typographic maps, please read our article SASS Typography Maps.

A quick note on baseline

If you’re working with a rigid, pixel based baseline, any responsive changes become far more complex. Considering the layout differences between what can be considered a mobile view and a desktop view (e.g. 1 column vs. 2 columns) it is sometimes desirable to change the heading size whilst retaining the paragraph size – or vice versa – as shown above. This means the baseline may no longer suit both styles. In a responsive world, however, I would argue that retaining the relative proportions between elements and styles across all viewports is more important than achieving a pixel-perfect baseline.

Global font-size

Not all projects requires this level of typographic declaration. Because you have defined all font-sizes in ems (you *have* defined all font-sizes in ems, right?), certain responsive changes can also be achieved very easily by changing the global font-size.

On the Primate site, the typographic changes from a “large” (desktop-ish) to “medium” (tablet-ish) viewport were mainly achieved by reducing the global font-size by 10%. Because of the reasonably generous 18px (1.125ems) for body text, the 10% reduction still yielded a readable size on medium viewports. One single bit of code and everything, including vertical rhythm, scaled down beautifully:

@media all and (max-width: 65em) {
body { font-size: 90%; }

Of course, things get trickier as the viewports change more drastically. At a certain point it’s no longer feasible to do all the scaling by changing the global font-size. For example, on our smallest breakpoint we wanted certain heading styles to shrink whilst retaining the size of the paragraphs. In this case we had two choices: either reduce the global font-size until the headings were at the right size, then override the paragraph style; or keep the global font-size in line with the paragraph and override the headings. It really depends how much manual tweaking one wants to do, but to me it makes sense to use the global font-size attribute to scale as many styles as possible and override the few that need attention after scaling.

For example:

p { font-size: 1.125em; }
h2 { font-size: 3.375em; }
h3 { font-size: 2.25em; }

// Reducing body font-size and overriding the paragraph style:

@media all and (max-width: 65em) {
body { font-size: 90%; }
p { font-size: 1.5em; }

// Or retaining body font-size and overriding heading styles:

@media all and (max-width: 65em) {
body { font-size: 100%; }
h2 { font-size: 3em; }
h3 { font-size: 2em; }

Now, this is a rough and ready way of scaling your typography, and I wouldn’t recommend it for those of you who are very particular about your hierarchy – changing the font-size on the body elements naturally affects the rest of your em values and maintenance becomes, in part, guesswork. Whatever floats your boat, really.

Responsive headings

“Lorem Ipsum” never ends up as final content in any project so making sure the heading sizes relate to real content, especially when considering different viewport sizes, is paramount. But even if you’re lucky enough to work with a copywriter and can work on size in relation to exact character counts, you’ll still have the issue of fluidity. What happens to massive headings when the viewport shrinks? Enter: fittext.js, a bit of javascript magic that fits your content to the width of the container. Using FitText means you can easily maintain proportionately large headings across the full spectrum of viewports.

Responsive typography across different devices

Using fittext.js, our main heading displays well on all devices.

A responsive workflow

In the context of this series of articles, it makes sense to talk about core design principles first and discuss responsiveness last. But in the real world, the best way to ease the burden of a responsive build is, like Mark Boulton put it, to think fluid first. Although this is most relevant in the context of layout, it also affects the way we think about typography. How will this heading look when the viewport shrinks and it wraps onto two or three lines? Is there flexibility in my measure, or will it get too short or too long as soon as the width changes? Asking these questions up front and throughout (as opposed to at the end of) the process can save a lot of backtracking down the line. Remember: responsive is not an add-on, it is the default.

Prototype early and keep tweaking

With a fluid mindset comes a fluid workflow. And far more powerful than simply *imagining* how your type will respond viewports is actually testing it. Even, or perhaps *especially*, if you use Photoshop to create visual concepts, get your type into the browser as soon as possible. Whether you code from scratch or use tools like Typecast, nothing beats assessing typography in a live environment. Indeed, when it comes to fluid and responsive, Photoshop is almost entirely redundant.

Having even a rudimentary prototype will give you the benefit of continuous tweaking of your styles, which can be done by introducing tweak points. Whereas break points are introduced when the layout breaks, tweak points are used to apply tweaks to individual styles at certain sizes to ensure a smooth transition across the spectrum of viewport sizes.

A big step away from old-fashion notions of following a pixel-perfect recipe to the letter, a fluid mindset and continuous tweaking makes for a more agile design process where big mistakes are spotted early and every iteration is an improvement on the last.

Final thoughts

Typography is largely based on design rules and guidelines, which means it is fairly easy to learn the basics. Mastering it, however, is hard. Attaining typographic perfection – if there is such a thing – is difficult and requires careful attention to a lot of considerations, from choosing fonts that work well together and suit the content to establishing a clear hierarchy using contrast in size, colour and style. Adding responsive to the mix certainly doesn’t make it any easier.

That said, we work in a field that boasts an incredible rate of innovation which constantly makes typography more accessible, more manageable and more fun to play around with. Whilst every project I work on brings new challenges (and frustrations), they also bring valuable lessons.

And besides, it’s not supposed to be easy – important things rarely are.

If you liked this article then why not subscribe to our RSS feed.

Author: Espen Brunborg

Espen can easily ruin conversations with questions about chimneys.


Showing One Comment

Leave a comment
  1. […] Responsive Type, part 4: Responsive consistency – Now, for something that really isn’t rocket science, consistency in responsive typography can be quite tedious. However, with the right approach you’ll find it an empowering experience. […]

Leave a Reply