Using @font-face with Octopress

This is an old post. It may contain broken links and outdated information.

Octopress comes with awesome support for Google Web Fonts, which lets you quickly and easily add fonts to your web site from Google’s large library, but Google Web Fonts have their drawbacks. Using one Google Web Font will have little impact on your site’s load time, but every additional font you add to your web page increases the page’s load time, as clients must use additional HTTP requests to pull the web fonts from Google’s servers while at the same time loading your page and its contents. Plus, sometimes you want to use a (free and legal) font that’s not in Google’s library.

There’s a workaround—a CSS method named @font-face (more info), which allows you to host your own fonts on your web server and serve them to clients along with your page. At first glance, this doesn’t seem too terribly different from simply including fonts from a web source like Google, but hosting your own fonts via @font-face on a web server with keepalive is much quicker than pulling them from a separate server, as far fewer HTTP sessions have to be used to load the page and its contents. Fewer sessions means faster page loading!

While Octopress comes with a ready-made method of adding Google Web Fonts, it’s not set up out of the box to use @font-face-served fonts. However, it’s pretty easy to change the configuration!

First: the conundrum

There are four separate types of web font files for you to consider, because unfortunately not every web browser understands every type of file. There’s plain old TrueType, which every browser except Internet Explorer can use; there’s Embedded OpenType, which only Internet Explorer understands; there’s Standard OpenType, which works with Firefox and Safari and Opera but not IE; and there’s the Scalable Vector Graphics format, which works with Safari and Opera and Chrome, but not IE or Firefox.

Way to go, Internet. Way to go.

At first blush, this seems like an annoyingly complex alternative to Google Web Fonts—you need four different files for every font type, because every browser wants a different file type. Fortunately, a lot of very smart people have thought about the problem and come up with some smart methods to simplify and automate the deployment of embedded fonts via @font-face. You still need a bunch of different files, but the CSS syntax that’s been settled on as standard will make sure that whichever browser you’re using selects and loads the appropriate font file.

Choosing a font bundle

There are three fonts in use on the Bigdinosaur.org blog: Arvo for titles, PT Serif for the main text, and Lato for the sidebar and footer text. All three are available from Google, but their licenses also make them available for use as @font-face embedded fonts, so I’ve switched them over.

By far the easiest way to get your fonts ready for use with @font-face is to have them be already prepared by FontSquirrel, an excellent repository of free web fonts. The fine folks at FontSquirrel have already done all of the hard work and packaged together a whole mess of usable fonts into @font-face-ready bundles, which include all the fonts’ weights and variations, in each of the four supported formats, along with example CSS and HTML you can use. Here’s ArvoPT Serif, and Lato (make sure to click the “@font-face Kit” link on each page to get the prepackaged kit).

There are lots of other methods available for getting @font-face-ready fonts, but FontSquirrel’s pre-built kits are by far the easiest. If you want to use another method, you’re on your own.

Making Octopress use @font-face

(Note: This section has been significantly modified from what I originally posted. I started this feature request on the Octopress GitHub site and Brandon Mathis, Octopress creator and maintainer, responded with a much more elegant method for configuring Octopress. Additionally, I’m using all available variations for each font, rather than just the “regular” ones as originally written. Woo!)

There are four steps necessary to make Octopress work with @font-face. The first is to stage the font files somewhere in Octopress’s source directory tree so that they get published to your web server. I elected to put my font files under source/assets/fontface/. The bundles from FontSquirrel contain all the fonts’ variations and weights; you only need to include the files relevant to the styles and weights you’re going to be using. Consult the example CSS and HTML provided with each bundle to determine which files you’ll need.

Once you’ve staged the files, you’ll next want to create a new Octopress configuration file in which to put the actual @font-face directive. Make a new file named sass/custom/_typography.scss and place in it the @font-face code for your fonts:

@font-face {
    font-family: 'Arvo';
    src: url('/assets/fontface/Arvo-Regular-webfont.eot');
    src: url('/assets/fontface/Arvo-Regular-webfont.eot?#iefix') format('embedded-opentype'),
         url('/assets/fontface/Arvo-Regular-webfont.woff') format('woff'),
         url('/assets/fontface/Arvo-Regular-webfont.ttf') format('truetype'),
         url('/assets/fontface/Arvo-Regular-webfont.svg#ArvoRegular') format('svg');
    font-weight: normal;
    font-style: normal;
}

@font-face {
    font-family: 'Arvo';
    src: url('/assets/fontface/Arvo-Italic-webfont.eot');
    src: url('/assets/fontface/Arvo-Italic-webfont.eot?#iefix') format('embedded-opentype'),
         url('/assets/fontface/Arvo-Italic-webfont.woff') format('woff'),
         url('/assets/fontface/Arvo-Italic-webfont.ttf') format('truetype'),
         url('/assets/fontface/Arvo-Italic-webfont.svg#ArvoItalic') format('svg');
    font-weight: normal;
    font-style: italic;
}

@font-face {
    font-family: 'Arvo';
    src: url('/assets/fontface/Arvo-Bold-webfont.eot');
    src: url('/assets/fontface/Arvo-Bold-webfont.eot?#iefix') format('embedded-opentype'),
         url('/assets/fontface/Arvo-Bold-webfont.woff') format('woff'),
         url('/assets/fontface/Arvo-Bold-webfont.ttf') format('truetype'),
         url('/assets/fontface/Arvo-Bold-webfont.svg#ArvoBold') format('svg');
    font-weight: bold;
    font-style: normal;
}

@font-face {
    font-family: 'Arvo';
    src: url('/assets/fontface/Arvo-BoldItalic-webfont.eot');
    src: url('/assets/fontface/Arvo-BoldItalic-webfont.eot?#iefix') format('embedded-opentype'),
         url('/assets/fontface/Arvo-BoldItalic-webfont.woff') format('woff'),
         url('/assets/fontface/Arvo-BoldItalic-webfont.ttf') format('truetype'),
         url('/assets/fontface/Arvo-BoldItalic-webfont.svg#ArvoBoldItalic') format('svg');
    font-weight: bold;
    font-style: italic;
}

@font-face {
    font-family: 'Lato';
    src: url('/assets/fontface/Lato-Regular-webfont.eot');
    src: url('/assets/fontface/Lato-Regular-webfont.eot?#iefix') format('embedded-opentype'),
         url('/assets/fontface/Lato-Regular-webfont.woff') format('woff'),
         url('/assets/fontface/Lato-Regular-webfont.ttf') format('truetype'),
         url('/assets/fontface/Lato-Regular-webfont.svg#LatoRegular') format('svg');
    font-weight: normal;
    font-style: normal;
}

@font-face {
    font-family: 'Lato';
     src: url('/assets/fontface/Lato-Italic-webfont.eot');
    src: url('/assets/fontface/Lato-Italic-webfont.eot?#iefix') format('embedded-opentype'),
         url('/assets/fontface/Lato-Italic-webfont.woff') format('woff'),
         url('/assets/fontface/Lato-Italic-webfont.ttf') format('truetype'),
         url('/assets/fontface/Lato-Italic-webfont.svg#LatoItalic') format('svg');
    font-weight: normal;
    font-style: italic;
}

@font-face {
    font-family: 'Lato';
    src: url('/assets/fontface/Lato-Black-webfont.eot');
    src: url('/assets/fontface/Lato-Black-webfont.eot?#iefix') format('embedded-opentype'),
         url('/assets/fontface/Lato-Black-webfont.woff') format('woff'),
         url('/assets/fontface/Lato-Black-webfont.ttf') format('truetype'),
         url('/assets/fontface/Lato-Black-webfont.svg#LatoBlack') format('svg');
    font-weight: bold;
    font-style: normal;
}

@font-face {
    font-family: 'Lato';
    src: url('/assets/fontface/Lato-BlackItalic-webfont.eot');
    src: url('/assets/fontface/Lato-BlackItalic-webfont.eot?#iefix') format('embedded-opentype'),
         url('/assets/fontface/Lato-BlackItalic-webfont.woff') format('woff'),
         url('/assets/fontface/Lato-BlackItalic-webfont.ttf') format('truetype'),
         url('/assets/fontface/Lato-BlackItalic-webfont.svg#LatoBlackItalic') format('svg');
    font-weight: bold;
    font-style: italic;
}

@font-face {
    font-family: 'PTSerif';
    src: url('/assets/fontface/PTF55F-webfont.eot');
    src: url('/assets/fontface/PTF55F-webfont.eot?#iefix') format('embedded-opentype'),
         url('/assets/fontface/PTF55F-webfont.woff') format('woff'),
         url('/assets/fontface/PTF55F-webfont.ttf') format('truetype'),
         url('/assets/fontface/PTF55F-webfont.svg#PTSerifRegular') format('svg');
    font-weight: normal;
    font-style: normal;
}

@font-face {
    font-family: 'PTSerif';
    src: url('/assets/fontface/PTF56F-webfont.eot');
    src: url('/assets/fontface/PTF56F-webfont.eot?#iefix') format('embedded-opentype'),
         url('/assets/fontface/PTF56F-webfont.woff') format('woff'),
         url('/assets/fontface/PTF56F-webfont.ttf') format('truetype'),
         url('/assets/fontface/PTF56F-webfont.svg#PTSerifItalic') format('svg');
    font-weight: normal;
    font-style: italic;
}

@font-face {
    font-family: 'PTSerif';
    src: url('/assets/fontface/PTF75F-webfont.eot');
    src: url('/assets/fontface/PTF75F-webfont.eot?#iefix') format('embedded-opentype'),
         url('/assets/fontface/PTF75F-webfont.woff') format('woff'),
         url('/assets/fontface/PTF75F-webfont.ttf') format('truetype'),
         url('/assets/fontface/PTF75F-webfont.svg#PTSerifBold') format('svg');
    font-weight: bold;
    font-style: normal;
}

@font-face {
    font-family: 'PTSerif';
    src: url('/assets/fontface/PTF76F-webfont.eot');
    src: url('/assets/fontface/PTF76F-webfont.eot?#iefix') format('embedded-opentype'),
         url('/assets/fontface/PTF76F-webfont.woff') format('woff'),
         url('/assets/fontface/PTF76F-webfont.ttf') format('truetype'),
         url('/assets/fontface/PTF76F-webfont.svg#PTSerifBoldItalic') format('svg');
    font-weight: bold;
    font-style: italic;
}

#{headings()}{
  @extend .heading;
  text-rendering: optimizelegibility;
  margin-bottom: 1em;
  font-weight: normal;
}

Note that these lines are copied directly from the FontSquirrel-provided example CSS files. Each section includes settings for loading each of the four different types of web font files discussed above. I was originally afraid that every single non-cached page load would cause the web server to have to send all four files for each font, but thanks to a lot of work by the FontSquirrel guys, the above configuration ensures that each of the most popular browsers and their derivatives request only the particular web font file that they can most easily read. This ends up being WOFF for just about everyone except Internet Explorer, because for all its innovation, IE still often rides the short bus to the Internet.

The last bit overrides the heading styles and forces heading fonts to be rendered in “normal” weight (that is, non-bolded). This is because Firefox, my web browser of choice, changed its font rendering method as of version 9 and started “over-bolding” bold headings, causing them to look terribly fuzzy and ugly. Forcing headings to “normal” works around the problem.

Now, to make use of the new typography override file we just created, we need to tell Octopress that we want it included when it’s generating the site. This requires editing of sass/custom/_styles.scss and adding in the following:

/* import typography */
@import "typography.scss";

Next, we need to add some lines to the _fonts.scss override file in sass/custom, because the names of the fonts have changed from Octopress’s default—”PT Sans” has become “Lsto”, “PT Serif” has become “PTSerif”, and Arvo is “Arvo”.

$sans: "Lato", "Helvetica Neue", Arial, sans-serif;
$serif: "PTSerif", Georgia, Times, "Times New Roman", serif;
$heading-font-family: "PTSerif", "Georgia", "Helvetica Neue", Arial, sans-serif;
$header-title-font-family: "Arvo", serif;
$header-subtitle-font-family: "Arvo", serif;
$heading-font-family: "Arvo", serif;

The last change to make is removing the Google Web Fonts entries in source/_includes/custom/head.html. You can simply comment them out, but the commented-out entries will still be included in every single generated page; it’s best to delete the contents of head.html and leave it as a zero-byte file.

After that, regenerate and publish your site, and then clear your browser’s cache and load it up. You should see your fonts served directly off of your web server.

This post now has a follow-up post about ensuring Nginx is serving your web fonts with compression.