CSS Typography: Techniques and Best Practices

CSS Typography: Techniques and Best Practices

In the first part of this series, we discussed some fundamental concepts pertaining to CSS typography. Now we are going to cover some excellent techniques, tips, tricks and best practices for dealing with typography on websites.

This is the second part of a three-part series of guides on CSS typography that will cover everything from basic syntax to best practices and tools related to CSS typography.

Better Web Typography with @font-face

For normal text blocks, using smart font stacks (as discussed in the first part) is a good idea, but for headings and short text blocks, more interesting fonts can be used with the help of @font-face.

When implemented correctly, @font-face is compatible with a wide range of browsers — yes, even IE.

Just include a copy of the font’s file on your web server and use the @font-face rule in your CSS code as follows:

@font-face {
  font-family: CurlzMTRegular;
  src: url(fonts/CurlzMTRegular.eot);

Then just use the font-family declared above with your CSS:

h1, h2, h3, h4, h5, h6 {
  /* Always use a font stack, even with custom web fonts! */
  font-family: CurlzMTRegular, Helvetica, Arial, sans-serif;

While IE4+ does support @font-face, the font does need to be in the .eot file format. Easy enough — just run any font of your choice through this converter first: ttf → eot Convertor.

For more information on @font-face, please read the following:

For easier implementation of @font-face, check out Font Squirrel’s @font-face generator.

Vertical Rhythm

Designing web typography is all about legibility and readability.

A leading factor for great legibility and readability is how the text flows vertically on the page. Is the text too squished together, or is it too far apart? This is where an understanding and practical implementation of vertical rhythm can come in handy.

Vertical rhythm is the spacing and arrangement of text as the user reads down the page.

Source: Get The Eye

Vertical rhythm deals primarily with font-size and line-height, but also top/bottom margins and padding.

The concept of vertical rhythm is simple: Line heights, margins, and padding should all be equal or within even proportion.

Here’s an example:

p, ol, ul, blockquote, pre, code {
  line-height: 18px;
  margin-bottom 18px;
  /* 1.5em provides good vertical spacing ( = 150% of the font-size) */
  line-height: 1.5em;
  margin-bottom: 1.5em;

Consider top margins and padding with blocks of text (e.g. paragraphs, lists, block quotes), as well as with images and other block-level elements. Try to use the same line-height or use multiples of it (e.g.18px, 32px, 64px, and so on for the example above).

Even proportions are easy to do with a bit of math. Let’s try to figure out what the line-height should be in the following example.

h1 {
  font-size: 2em;
  line-height: ?;

If the line-height for the body is set to 1.5em, then we just need to divide that by our font-size to maintain the proportion: 1.5em/2em = 0.75em.

h1 {
  font-size: 2em;
  line-height: 0.75em;

For font sizes bigger than the line-height, line-height must be decreased to match the baseline grid. For font sizes smaller than the line-height, we must increase the line-height.

We can determine the line-height for smaller font sizes with the same bit of math. Let’s try this again, but this time, our font-size is smaller than the body element’s line-height.

h2 {
  font-size: .7em;
  line-height: ?;

If the body‘s line-height is still 1.5em, then we’ll take it and divided by our font-size: 1.5em/.7em = 2.14em.

h2 {
  font-size: .7em;
  line-height: 2.14em;

For more information on creating baseline or vertical rhythm in web page layouts, look through the resources listed below. There is also a handy vertical rhythm generator, just in case you don’t want to do all that math.

Working with Text and Whitespace CSS Properties

@font-face and vertical rhythm can sometimes get overwhelming, so let’s slow things down a bit and get back to some basic techniques.

Text CSS Properties

The CSS text property group contains several properties for dealing with the style of text. Having a good understanding of these properties can help bring blocks of text in your designs to a more user-friendly level.

Here are some text CSS properties (their names are self-evident to what they’re for):

Let’s see how one of these properties works by way of an example. In the following example, we will indent the beginning of all paragraphs:

p {
  text-indent: 3em;

Text Direction

You can set the direction of the text by using the direction property. The default direction is ltr, which is short for left to right. Suppose we wanted to reverse that, then we can set direction to rtl.

p {
  direction: rtl;

The direction property is not very popular because it has a very specialized purpose, but it can come in handy when working with other written languages. Many middle eastern languages, for example, are read right to left.

White-space, Letter-spacing, and Word-Spacing

These properties provide spacing between words and letters.

The white-space property controls how text wraps inside of its parent element. Values can be normal, nowrap, pre, pre-line, pre-wrap and inherit.

The word-spacing property affects the space in between words. Values can take any CSS unit of measurement (such as 0.5em or 5px).

The letter-spacing property is similar to the word-spacing property, however, it deals with the spacing in between individual characters instead. Values of this property can take any CSS unit of measurement.

Text Shadows

CSS3 gives us a few more CSS properties for use on web typography. One property that’s a new addition to CSS is text-shadow. Here’s the style rule for giving paragraphs a nice text shadow.

p {
  text-shadow: 1px 1px 1px #000;

From: Neutron Creations

To create inset text, you can use negative values as such:

h1  {
  /* Use negative offsets to create inset text. */
  text-shadow: #000 -1px -1px 0;

To see text-shadow in action, check out this tutorial on how to create inset typography using CSS3.

CSS Typography Best Practices

What follows is a review of best practices that we’ve already covered, as well as a few additional ones. The key concept to keep in mind is that CSS typography is all about creating readable type that improves the user experience.

Serif or Sans serif?

There isn’t any conclusive study that indicates one group of type is more legible than the other. What affects legibility the most are the CSS properties we have discussed, such as font-size and letter-spacing.

For serif fonts, use more line-height, letter-spacing, and perhaps even word-spacing because serif fonts need some space to breathe and express their curvatures.

For sans serif fonts, the simpler font style can allow for tighter spacing and smaller font sizes with the least negative effect on legibility.

Semantic Markup

Always use proper markup. For example, use <strong> instead of <b> and <em> instead of <i>, then use CSS to style them.

Use headings (h1-h6) appropriately: to delineate sections of your content into logical groups. Using <h2> after <h1> means that the section that follows is a sub-section of <h1>. Use CSS to style them any way you want, but keep your markup semantic.

Use HTML tags to add value to the content of the HTML document, and use CSS to visually style them. For example, use <small> instead of <p class="smalltext">.

Create Baseline Styles

It’s always good practice to reduce the guessing game that browsers play when they can’t find a style rule for a particular element. Don’t forget to style basic HTML elements.

h1, h2, h3, h4, h5, h6 {  }
p { }
ol, ul { }
a { }
blockquote { } 
pre, code { }
small { }

Use 1.5em for Line-Height

1.5em is the most common and recommended baseline line-height; it states that the line-height is +50% of the text’s font-size, giving blocks of text some vertical breathing room.

This isn’t to say that any other line-height value is bad; but when in doubt, 1.5em is a safe bet.

Using a relative unit of measurement for line-height also takes out the math involved in having to figure out the corresponding line-height, as shown in this example:

p {
  font-size: 12px/1.5em;

For a 12px font-size, an 18px line-height could be used to achieve the exact same result, but then you would have to recalculate what that value would be if your font-size changes for other elements.

Use Shorthand CSS

Always use shorthand wherever you can as it’s the conventional way of writing CSS nowadays.

Here is the shorthand structure for the font property:

font: [font-style] [font-size]/[line-height] [font-family 1, font-family 2, ..., font-family n]

For example:

p {
  font: normal 12px/1.5em Arial, Helvetica, sans-serif;


In this part, we covered some techniques, tricks, and best practices for CSS typography. In the next part, we will present you with some examples of great CSS typography as well as some tools that you can use to make your life easier.

Related Content

About the Author

Kayla Knight is a web designer and web developer who loves coding way too much for her own good. She does freelance design/development work and helps run the XHTML Shop. Connect with her by visiting her website and following her on Twitter @ KaylaMaeKnight.

This was published on Mar 10, 2011


unfortunately font-face rendering on Windows is often horrible, so if you design on a Mac, always test your fonts on a Windows machine when you’re considering them for your design.

for line-height, I use the “number” value instead of ems, as it’s always proportional
From the W3C : “The used value of the property is this number multiplied by the element’s font size.”
A good explanation :

Joshua Chase Mar 10 2011

Wow, super in depth and very easy to follow. I will try to be better at following semantic markup, I’ve been super guilty of using <b> & <i> A LOT. Thanks for this you got mad font skillz.

Michael Gunner Mar 10 2011

I think you miss the boat when talking about fontface, you don’t go into any detail regarding what browsers support what formats.

The Font Squirrel generator is the only one worth bothering with because it creates your font in multiple files that makes your font compatible with all modern browsers.

Also, your xhtmlshop website doesn’t work for me.

Craig Wann Mar 10 2011

This is really great. I’ve been looking for some direction on the font-size/margin-padding/line-height relationship. Definitely some things I can change!

Quick question: In the first example in the vertical rhythm section, you style line-height and margin-bottom twice, once in px and once in em. Is there a reason why you did this?

cancel bubble Mar 10 2011

“Always use proper markup. For example, use <strong> instead of <b> and <em> instead of <i>, then use CSS to style them.”

This seems kind of if’y now with HTML5 as several historically presentational tags have been given new semantic meanings in HTML5.

Let’s look at <i> and <b> and compare them to the semantic stalwarts <em> and <strong>. In summary:

<i> — was italic, now for text in an “alternate voice,” such as foreign words, technical terms and typographically italicized text

<b> — was bold, now for “stylistically offset” text, such as keywords and typographically emboldened text

<em> — was emphasis, now for stress emphasis, i.e., something you’d pronounce differently

<strong> — was for stronger emphasis, now for strong importance, basically the same thing (stronger emphasis or importance is now indicated by nesting)

Oguzhan Mar 10 2011

helpfull article, especially @font-face is great!

Awesome, thank’s !

Alysson Franklin Mar 10 2011

gr8 article. A good tip is to use text-shadow to avoid aliasing.

text-shadow:0 0.05em 10em rgba(0, 0, 0, 1);

the 10em, for the depth will deal with the aliasing, without create a ‘real’ shadow. Since the depth is too high, there’s no shadow to be filled but the aliasing at this point is removed.

Strixy Mar 10 2011

Something to mention WRT the Semantic Markup section. This advice is also relevant for SEO.

I’m lost, however, with the Vertical Rhythm section where you say headers should be

font-size: 2em;
line-height: 0.75em;

Setting a line height less than the font-size risks creating a nasty mashed line spacing for headers depending on the end users resolution and risks breaking other elements in and around the block. I’ll mention that I’m mostly concerned with this where user generated content might appear in a contained header. I think that goes for any font using ’em’ as it’s measurement for a dynamic site. You’ll notice that major sites, eg. Facebook, use px for font declarations.

Young Mar 10 2011

I recently blogged about using @font-face with non-English characters, if it’s of interest to anyone (my example’s for Korean):

I also tend to use % values for line-height instead of em’s. Another thing I like to do often is put in a tiny bit of letter-spacing, like 0.05em or so, for readability.

Przepisy Mar 10 2011

Wow, thanks for this article,i was looking for something like that, especially with padding, and this really helps me:)

PixelTunnelVision Mar 10 2011

Great articles. Only thing I want to note is how you suggest using small tags instead of class-defined p/container tags. A lot of places, like W3schools and books, suggest the opposite. In fact, W3schools even says “Font-style tags like small are defined in HTML4, but it is strongly recommended to use CSS styling instead.”

David Mar 10 2011

Great article guys, really useful for the margin-bottom on p tags.

Graham Mar 11 2011

Thanks for the article Kayla. Came along at the right time for me, especially the part dealing with vertical rhythm and the links are helpful too.

Like cancel bubble pointed out, it’s maybe worth looking further into the use of <b> and <i> – the article at HTML5Doctor along with the discussion is quite interesting.

Gregor Colnik Mar 12 2011

Great advices. I will definitely try this @fontface advantage on my next css project.

Brad Davis Mar 14 2011

Informative article for peeps to learn and brush up on their markup. Thanks.

Vladislavs Judins Mar 14 2011

Can’t wait to see examples. Is it coming some time soon?

Michael Mar 14 2011

Great stuff! I have already forwarded it onto some others to take a look. I will definitely come back to review this article. Thanks again

lvacs Mar 15 2011

Wow! Great tutorial Kayla! You have gone in depth and explained this really well. Thanks!

Diogo Mar 15 2011

Keep up the good work!

“The concept of vertical rhythm is simple: Line heights, margins, and padding should all be equal or within even proportion.”

It’s one of many options. You might even give it a name like, “Symmetrical vertical rhythm”. But it’s a mistake to rigidly stick to line-height and margin-bottom being equal. It is quite acceptable to have no extra leading at all (indenting paragraphs) or as little as half an em.

But all in all, an excellent article. Every time I see a link to an article on typography, I have to follow it, and yours is one of the better ones I’ve seen!

Irina Mar 22 2011

Great article, using custom fonts can really make a difference to a design. I would add though that if you do use web fonts you need to make sure that you purchase the right licence (it needs to say that you are allowed to use the font on the web), unless it’s a free font.
There are some good free fonts available on google web fonts, kernest and However, using custom fonts may slow down your website and sometimes a client may want a specific font. In that case is a great source. They host fonts and you can test how fonts will look like on a screen.

Qaiser May 09 2011

Nice article about understanding typography concepts. especially for beginners who dont know the difference between critical things like line height and font sizes. nice way to explain

Chris Sep 27 2011

Note that serving fonts by way of your own web host can be processor and bandwidth intensive. Just think, every page load that isn’t cached will have to serve up the fonts identified in your stylesheet. Ouch.

Geoffrey Hale Jun 13 2012

Ah! This part was definitely my favorite:

font: [font-style] [font-size]/[line-height] [font-family 1, font-family 2, …, font-family n]

Thank you!!!


I liked the CSS shorthand style of writing. Nice way to describe the whole things. Thanks a lot!

This comment section is closed. Please contact us if you have important new information about this post.