Vertical Rhythm and Responsive Typography: A Starting Point

Let me start by pointing out that I am not an expert typographer. In fact, I wouldn’t consider myself a typographer at all. However, as a web developer I deal with typography on a regular basis and do my best to display content in a responsible manner. Today I want to talk about vertical rhythm, baseline grids, and responsive typography. I also want to propose a simple, responsive, baseline grid that can be used to create a consistent vertical rhythm.

Definition of Terms

Before moving on, I want to quickly define a few terms that will be used repeatedly in this tutorial.

  • Vertical rhythm – The vertical spacing of lines and elements on a page.
  • Baseline Grid – A one dimension (vertical) grid used to set a consistent vertical rhythm.
  • Responsive Typography – Adjusting typographical styles based on screen size.

In this tutorial we will be looking more at the implementation of these ideas than the theories and best practices surrounding them. Typecast has a number of helpful articles on these topics and I highly recommend readingĀ 4 Simple Steps to Vertical Rhythm andĀ A More Modern Scale for Web Typography for more information.

Implementing Vertical Rhythm

As usual, we’ll start with styles intended for mobile devices. Mobile devices have shorter line lengths, and therefore require less spacing between lines to achieve maximum readability. As line lengths increase, line heights need to increase accordingly. We’ll start with a base font size of 16px (1rem) and a line height of 20px (1.25rem) and move up from there. I don’t claim this code is perfect, but it should give us a good start in creating a consistent baseline grid. I just want to make a couple notes before diving into the code,

  • These styles assume that the margin and padding have already been set to zero for all elements.
  • For more on using “rem” for font sizing, check out Jonathan Snook’s article Font Sizing with rem.

Let’s start at the beginning.

*{
	font-size: 100%; /* 16px */
	line-height: 1.25rem; /* 20px */
}

The * character is a wild card that represents every element. As you can see, we’ve used it to give every element a font size of 100% (16px) and a line-height of 1.25rem (20px).

h1,
h2,
h3,
h4,
h5,
h6,
p,
ol,
ul,
table,
blockquote,
pre{
	margin-bottom: 1.25rem; /* 20px */
}

Next we have a long list of elements with a margin-bottom of 1.25rem (20px). This insures that the spacing between elements keeps everything on our 20px baseline grid.

h1{
	font-size: 2rem; /* 32px */
	line-height: 2.5rem; /* 40px */
}

h2{
	font-size: 1.625rem; /* 26px */
	line-height: 2.5rem; /* 40px */
}

h3{
	font-size: 1.375rem; /* 22px */
	line-height: 2.5rem; /* 40px */
}

h4{
	font-size: 1.125rem; /* 18px */
	line-height: 2.5rem; /* 40px */
}

h5{
	font-size: 1rem; /* 16px */
	line-height: 1.25rem; /* 20px */
}

h6{
	font-size: 0.875rem; /* 14px */
	line-height: 1.25rem; /* 20px */
}

Here we have the styles for the heading elements. I’m not completely satisfied with this section, but to keep a consistent rhythm without the use of Javascript some compromises must be made. Ideally the line height would change along with the font size as we move from h1, to h2, to h3… However, doing that would throw off the vertical rhythm. We could compensate for that by adding corresponding margins, but if a heading was too long to fit on a single line, our margin would no longer be the right height. For now I’ve chose to just stick with a 40px line height until the heading font size is small enough to use the standard 20px line height.

blockquote{
	padding:  1.25rem 1.5rem 0 1.5rem; /* 20px */
}

blockquote p{
	margin-bottom: 0;
	padding-bottom: 1.25rem; /* 20px */
}

blockquote cite{
	display: block;
	margin-top: 1.25rem; /* 20px */
	text-align: right;
}

Blockquotes are interesting because we have to account for paragraph tags and cite tags that may be placed inside them. WordPress automatically places paragraph tags inside blockquotes, so we have to make sure we handle that gracefully. As you can see above, the blockquote has a top padding of 1.25rem, but the bottom padding is set to 0. Normally we give the paragraph element a bottom margin equal to our line-height, but here we replace it with a bottom padding. Finally, make sure the cite tag is styled in a way to make it distinguishable from the rest of the quote.

table{
	border-collapse: collapse;
}

th{
	line-height: 2.5rem; /* 40px */
	padding: 0 0.625rem; /* 0 10px */
}
td{
	padding: 0 0.625rem; /* 0 10px */
}

By default, small spaces are left between table cells, which throws off our vertical rhythm. Here we’ve collapsed those spaces using border-collapse in order to bring the table cells together. This may not be ideal for display purposes, but it keeps the vertical rhythm. This tutorial is just a starting point and you may need to make adjustments to fit your needs. We’re giving the th and td tags a little horizontal padding so that the text inside the cells doesn’t run together.

ol,
ul{
	margin-left: 1.5rem; /* 24px */
}

Since we’res assuming all the margins have been reset to 0, we have to add a left margin back to the list elements so that nested lists display properly.

sub{
	font-size: 0.625em; /* 10px */
	vertical-align: bottom;
}

sup{
	font-size: 0.625em; /* 10px */
	vertical-align: top;
}

The sub and sup tags are given smaller font sizes and vertically aligned to move them up and down without extending past the line height given to the parent element.

em,
var,
strong,
p code{
	line-height: 1rem; /* 16px */
}

Finally, there are a few elements that like to take up a little more space than they should. This section is kind of a hack, but it seems to keep these elements in check.

Extending Vertical Rhythm Responsively

To adjust the vertical rhythm of the site responsively based on screen size, we can use a CSS media query to load a new set of styles when the screen width increases beyond a certain size. In this example, I’ve used 600px as the breakpoint.

@media screen and (min-width : 600px)

The styles applied by the media query are almost exactly the same as the styles we’ve covered already, so I’m not going to go through them step by step. Just notice that the standard line-heights and margins have been changed from 1.25rem (20px) to 1.375rem (22px) and the heading font sizes have been increased. If you wanted to increase the baseline grid further, you could simply change all the standard line-heights and margins to something else, like 1.5em (24px). Here’s all the code at once, including both the mobile styles and the desktop styles inside the media query:

/* =Typography (mobile)
-------------------------------------------------------------- */
*{
	font-size: 100%; /* 16px */
	line-height: 1.25rem; /* 20px */
}

h1,
h2,
h3,
h4,
h5,
h6,
p,
ol,
ul,
table,
blockquote,
pre{
	margin-bottom: 1.25rem; /* 20px */
}

h1{
	font-size: 2rem; /* 32px */
	line-height: 2.5rem; /* 40px */
}

h2{
	font-size: 1.625rem; /* 26px */
	line-height: 2.5rem; /* 40px */
}

h3{
	font-size: 1.375rem; /* 22px */
	line-height: 2.5rem; /* 40px */
}

h4{
	font-size: 1.125rem; /* 18px */
	line-height: 2.5rem; /* 40px */
}

h5{
	font-size: 1rem; /* 16px */
	line-height: 1.25rem; /* 20px */
}

h6{
	font-size: 0.875rem; /* 14px */
	line-height: 1.25rem; /* 20px */
}

blockquote{
	padding:  1.25rem 1.5rem 0 1.5rem; /* 20px */
}

blockquote p{
	margin-bottom: 0;
	padding-bottom: 1.25rem; /* 20px */
}

blockquote cite{
	display: block;
	margin-top: 1.25rem; /* 20px */
	text-align: right;
}

table{
	border-collapse: collapse;
}

th{
	line-height: 2.5rem; /* 40px */
	padding: 0 0.625rem; /* 0 10px */
}
td{
	padding: 0 0.625rem; /* 0 10px */
}

ol,
ul{
	margin-left: 1.5rem; /* 24px */
}

sub{
	font-size: 0.625em; /* 10px */
	vertical-align: bottom;
}

sup{
	font-size: 0.625em; /* 10px */
	vertical-align: top;
}

em,
var,
strong,
p code{
	line-height: 1rem; /* 16px */
}

@media screen and (min-width : 600px) {

	/* =Typography (tablet & desktop)
	-------------------------------------------------------------- */
	*{
		font-size: 100%; /* 16px */
		line-height: 1.375rem; /* 22px */
	}

	h1,
	h2,
	h3,
	h4,
	h5,
	h6,
	p,
	ol,
	ul,
	table,
	blockquote,
	pre{
		margin-bottom: 1.375rem; /* 22px */
	}

	h1{
		font-size: 2.5rem; /* 40px */
		line-height: 2.75rem; /* 44px */
	}

	h2{
		font-size: 2rem; /* 32px */
		line-height: 2.75rem; /* 44px */
	}

	h3{
		font-size: 1.5rem; /* 24px */
		line-height: 2.75rem; /* 44px */
	}

	h4{
		font-size: 1.125rem; /* 18px */
		line-height: 2.75rem; /* 44px */
	}

	h5{
		font-size: 1rem; /* 16px */
		line-height: 1.375rem; /* 22px */
	}

	h6{
		font-size: 0.875rem; /* 14px */
		line-height: 1.375rem; /* 22px */
	}

	blockquote{
		padding:  1.375rem 1.5rem 0 1.5rem; /* 22px 24px 0 24px */
	}

	blockquote p{
		margin-bottom: 0;
		padding-bottom: 1.375rem; /* 22px */
	}

	blockquote cite{
		display: block;
		margin-top: 1.375rem; /* 22px */
		text-align: right;
	}

	table{
		border-collapse: collapse;
	}

	th{
		line-height: 2.75rem; /* 44px */
		padding: 0 0.625rem; /* 0 10px */
	}
	td{
		padding: 0 0.625rem; /* 0 10px */
	}

	ol,
	ul{
		margin-left: 1.5rem; /* 24px */
	}

}

As always, you can let me know via the contact form or on twitter if you have any questions, comments, or suggestions for improving this baseline grid. Thanks!