Getting type to the Web

Published • 04 Mar 2011

The last year and a half has seen a rekindling of the interest in web typography, marked by the popularity of sites like (now trending on 67,000+ subscribers) and the growing number of typography articles pertaining to the subject across the web design and development community. Typography remains central to aesthetics, accessibility, and of course legibility. Those who master it and apply it to the Web have been admired for the ingenuity of their work, both stylistically and in their technical implementation.

Typography brings aesthetic order to information, aiding reading and navigation. Typography differentiates; it is a core element of branding. The bottom line is that good typography when applied to the Web creates web experiences that are easier and more pleasurable to use. This renewed enthusiasm in the field has turned a new page in web typography, and can chiefly be attributed to the rise of web fonts and their growing availability across the browser range, permitting us to extend beyond the core ‘web safe’ fonts (Andale Mono, Arial, Courier, TNR, Impact, Verdana, Georgia, and Trebuchet MS). Good typography begins with selecting typefaces appropriate to the text being set; the right typeface or group of faces for the right work. Setting a graphic horror novel in TNR or Helvetica would be inappropriate to the genre of the book, and the graphical medium it utilises. However a good page-turner novel (for which a transitional typeface like TNR is far better suited) would be difficult to read if it were set in a script typeface.

Typography exists to honor content

Selecting good typefaces is one step and is perhaps made harder now that we have more than the core ‘web safe’ fonts to work with (or those that are next most likely to be installed). Implementing them for our web sites is another technical hurdle. This article highlights the options for getting type on the Web and then cover each method in detail while retaining a strong focus on web standards.

Options for bringing fonts to the Web

Browsers implement custom fonts in different ways. This disparity boils down to an open versus closed debate — locking down the methods to secure the font assets from easy download from the web site which uses them versus a more open model built on trust. To some degree this debate bears similarities to the one that raged when images were first available on the Web, and similarly, these differences in implementation have largely been settled as WOFF is hopefully finalised as a standard by the W3C.

There are a variety of methods available to us to bringing fonts to the Web for typesetting. They are, in loose historical order of availability:

  • installed fonts (mostly web-safe);
  • Flash (e.g. sIFR) and other JS replacement techniques;
  • Cufón et al.;
  • webfonts: EOT/EOT Lite via @font-face;
  • webfonts: OT/TT via @font-face;
  • webfonts: SVG via @font-face;
  • webfonts: WOFF via @font-face;
  • and hosting & licensing services.

Installed fonts

Calling upon installed fonts is the simplest and easiest method. Within our CSS stylesheets we simply call upon a list of fonts via the font-family property and order them as per:

  • desired
  • fallbacks
  • generic (e.g. serif, sans-serif, monospace,)

For example, a transitional serif font stack:

p {
        'Times New Roman',

And a neo-grotesque stack:

h1, h2, h3, h4, h5, h6, h7 {
        'Helvetica Neue',

If the first available font in the stack is not installed on the client machine it obviously cannot be used for rendering, so it skips to the next attribute in the list, and so on until an available font is found. Good font stacks reflect what is likely to be installed on the machines of our users by taking into account default font libraries for popular operating systems. This allows us to cautiously extend beyond the core ‘web-safe’ fonts by placing another preferred font in the list which still is quite popular.

Flash replacement techniques

Flash replacement is a nifty method of replacing HTML text with Flash text with the help of a JavaScript file. The most popular technique is the Scalable Inman Flash Replacement (sIFR).

While it has support for sub-setting, it is not a feasible long-term solution to bringing truly custom fonts to the Web, particularly with its reliance on non-standard technologies and use of JavaScript. It is also performance demanding with a longer page load time (predominately due to the number of requests made for the required Flash, JavaScript, and CSS files). Its best uses are for setting a single heading or a small series of headings, but it is far from practical for setting body copy.

Cufón et al.

A range of other JavaScript replacement options became available in an effort to get the job done without Flash. Cufón is perhaps the most popular of these with an online front-end for easy conversion of the font data into JavaScript that provides good support for sub-setting with a range of other options on kerning, scaling, cross object resource sharing (CORS) to limit use for a list of domains.

Cufón converts fonts paths to VML (now for the most part deprecated by SVG) stored in JSON and rendered by the JavaScript rendering engine within the user agent. While it has good browser support it also is not a viable long-term solution due to its poor accessibility.

webfonts: EOT/EOT Lite

Since the end of 1997 Internet Explorer 4 has supported Embedded OpenType (EOT) for use through the @font-face element that was introduced in the CSS2 specification. Microsoft’s EOT permitted the download of custom font assets for use in rendering type on a web page (and has seen helped bring writing systems that are not supported by default to the Web) without making those assets useable on the desktop and abetting font copyright infringement.

EOT subsets, compresses, and finally encrypts TrueType font assets. CORS is provided by way of a ‘trusted roots’ list. Unsurprisingly with a proprietary compression method, a proprietary encryption/decryption process, and support only in Internet Explorer, EOT and even EOT Lite (which omits the proprietary MTX compression and the CORS trusted root listing) is a proprietary and non-standard solution as a webfont format.

EOT files can be created with Microsoft’s WEFT, or through ttf2eot, an open source implementation of the converter. WEFT is worth skipping because:

  • it uses the MTX compression method and is out-performed by other methods like gzip;
  • it only works on Windows and tends to perform unreliably under emulators (e.g. Parallels);
  • ttf2eot does not compress — use server-side compression instead;
  • Font Squirrel’s @font-face web front-end to ttf2eot is simple and easy to use.

webfonts: OT/TT

These work in a similar fashion to EOT webfonts in being referenced in the @font-face src: declaration to be downloaded and used directly to render type.

OpenType/TrueType is a feasible, open method of providing webfonts with a fairly good browser support (Safari 3.1+, Firefox 3.5+, Opera 10+, Chrome 4+; IE9 beta, and Android 2.2+). Of course instantly apparent is that the font assets are not encrypted, bound to any trusted roots, or CORS limitations and are available in a format readily usable on the desktop outside the browser environment (e.g. desktop publishing and word processing) once easily downloaded. Further, sub-setting and compression is not automatic and the responsibility font assets’ host.

webfonts: SVG

These are also part of the @font-face webfonts specification, SVG are referenced in the src: declaration just like EOT, OTF, or TTF fonts.

Again, SVG files are not obscured and thus easily available for download for use beyond the web page they are referenced in. Browser support is fairly widespread also (Firefox 3.5+ Chrome 0.3+, Opera 9+, Apple iOS1+, and Safari 3.1+), and, as with OT/TT webfonts, sub-setting and compression comes down to the host.

SVG files can be gzip compressed into .svgz files.

webfonts: WOFF

Flash/JavaScript replacement techniques and then Cufón have shown web typographers and technologists that a dedicated, open, and standardised webfont format was required. Microsoft’s EOT, Ascender’s EOT Lite extension, OT/TT and SVG direct font linking all competed on the open ground of the Web in a popularity contest to see which would be adopted first with the most widespread use and browser support. This competition revived the discussion at the W3C over an open, standardised webfont format. WOFF seeks to fill this gap.

Working with the @font-face declaration WOFF combines compressed sfnt-font data (PostScript, TrueType, or OpenType) with a XML meta-data bundle to create an open font file perfect for bringing fonts to the Web. WOFF files are created with the open source sfnt2woff. Sub-setting comes down to the host. CORS is available via HTTP response headers. Ultimately the font data can still be extracted, but, if sub-setted, de-packing a WOFF font file to extract useful font data for external use requires effort and it’s likely the resulting font data will be limited (due to the sub-setting).

Currently WOFF is supported in Firefox 3.6+, WebKit, Chrome 5+, and the IE9 development beta.

Hosting & licensing services

While the search for a good, open, and standardised webfont format was underway many foundries and a number of technologists began exploring their own ideas in bringing custom fonts to the Web. Since a number of web hosting and licensing services have sprung up offering a library of fonts at a variety of free and commercial plans: TypeKit, Kernest, Fontdeck, Monotype’s, Typotheque’s webfont service, &c. Create an account, browse the library, select, pay, inject a few lines of code, refresh; done.

Image: a screenshot of the web site homepage taken December 2010.

The homepage.

On the technical side these services provide the right or best font (EOT, OT/TT, SVG, and soon WOFF) to the right browsers — if a query is made by a user using Internet Explorer an EOT file would be served. Sub-setting is done by the providers, depending on which languages and features you are likely or wish to use, and compression is also handled service-side.

The implementations are largely standards-based and provide very extensive browser support. The web front-ends are easy to use, and have an ample library of quality fonts up for selection between all of the services providers.

Finding freely-licensed fonts

Now that we can implement custom fonts on the Web using @font-face you might wonder where to obtain freely-licensed and free of charge quality fonts for use on the Web (and elsewhere). Places worthy of your attention:

Using @font-face

If you choose not to use a hosting and licensing service and instead opt to host and reference font files using @font-face yourself, creating the various font files and getting the syntax for the declaration correct might seem daunting. In reality using a bullet-proof syntax from to Paul Irish and Font Squirrel’s @font-face web front-end it is a piece of cake.

Creating @font-face webfont files

If you have a font you want and can use on the web your font is likely to be an OT/TT or PostScript file, which you need to create compressed and sub-setted EOT, OT/TT, WOFF, and SVG files for. The easiest way of meeting all these goals is to use Font Squirrel’s @font-face web front-end:

Image: a screenshot Font Squirrel’s @font-face Kit Generator.

The Font Squirrel @font-face Kit Generator.

Simply select and upload your font after which you can take the easy route and use default settings to let Font Squirrel to generate your kit for you to download, or you can take the ‘Expert’ path and fine tune just about every nuanced detail of the resulting font files. Accessing custom sub-setting allows precision control over sub-setting character types, sub-setting for languages, sub-setting via Unicode tables and ranges, as well as specific characters, presenting a list of all the characters that will be included in the resulting sub-setted font files.

When you are done download your kit ready for deployment.

‘Bullet-proof’ @font-face declarations

Writing a bullet-proof @font-face is not difficult, but there are some gotchas to watch out for. Let’s get to work.

Basically we want to feed Internet Explorer an EOT file and feed other browsers OT/TT files while providing forward support for WOFF-supporting browsers. The order in which we list these files in the src: declarations is important because (surprise, surprise) Internet Explorer will otherwise needlessly download the other files even though it cannot handle them, wasting page load time on unnecessary additional connections and traffic. Thus, using Museo:

@font-face {
  font-family: 'Museo 500';
  src: url('Museo500.eot');
  src: local('?'),
       url("Museo500.woff") format("woff"),
       url("Museo500.otf") format("opentype"),
       url("Museo500.svg#museo") format("svg");

Dissecting this, we start by giving the font we want to link a name we can reference for font stacks. The attribute is arbitrary.

Next comes the EOT file, first in the src: list as to avoid IE having that aforementioned fit.

Then the local src: call, though we actually omit specifying a local src: declaration, instead entering ‘?’. There are two main reasons for this. Firstly, it prevents the (although rather unlikely) chance that the user will have a font installed (which will be used instead, saving the download) that matches your local attribute but is not actually your desired font wrecking your font stack and possibly your design. It is very unlikely that a font installed will be named ‘?’, and under the OpenType specification any two-byte unicode characters will not work as a font name, excluding Macs entirely from this problem with this solution.

Secondly, there a variety of bugs still evident in Webkit and Mac OS X in handling local references. If you feel certain that there is a high likelihood that a user could have your desired font installed (e.g. it is a freely available and freely licensed popular typeface like Museo) and it would be unlikely that there could be another font installed that bears the same local reference then making local entries is quite OK — it comes to weighing up the likelihood of either instance.

In case you do want to define a local src: reference it might seem odd that you can write two slightly different entries for local in src:, for example: src: local("Museo 500 Italic"), local("Museo500-Italic"),. Huh? This is because some browsers refer to local fonts via their PostScript names. To find the local names for a font under Mac OS X open Font Book, select your font and select PreviewShow Font Info (or ⌘ + I). For Windows there is a downloadable Font properties extension. Once installed right-click and zip to Properties on a font file and click on the Names tab to see the name details.

Image: Screenshot of Mac OS X Font Book demonstrating the Font Info view mode

Screenshot of Mac OS X’s Font Book demonstrating the Font Info view mode.

Then come the WOFF and OT/TT src: definitions, followed by the SVG definition. Note the #museo in "Museo500.svg#museo". This is because SVG files are XML files and thus we need to reference the starting div (e.g. after the opening meta-data) that references the start of the font vector paths.

That’s it; done. Credit and kudos goes to Paul Irish for revealing nitty-gritty details of writing bullet-proof @font-face syntax definitions.

Problem: ‘double-setting’ styles and variants

When using @font-face, we are likely to be dealing with separate font files of the same family for the various font styles, e.g., foobar-regular.otf, foobar-italic.otf, foobar-bold.otf, foobar-smallcaps.otf, and so forth.

This can become an issue — consider elements such as strong and em which are styled with setting the face in a bold and italic respectively. If we declare the italic as we would normally in the CSS (as we would to get the style into our design) what will happen is that the italic is digitally italicised (fake italics) by the font rendering engine. Result? Our italic font or bold font is taken and digitally italicised or boldened, creating ugly results.

If we avoid or overwrite the various declarations (e.g. em { font-style: normal; }) and for whatever reason our desired @font-face font is not available, we rob other fonts in the font-stack of their styling. We overcome both these issues by setting the font styles within the @font-face declaration, informing the user agent that we are in fact defining an italic or a bold already and that these should be left as is when used to set something that is declared via the CSS to be italic or bold:

@font-face {
  font-family: 'Museo 500';
  font-style: italic;
  src: url('Museo500.eot');
  src: local('?'),
       url("Museo500.woff") format("woff"),
       url("Museo500.otf") format("opentype"),
       url("Museo500.svg#museo") format("svg");


Caveats, drawbacks, and compromises exist in everything, and type setting is not excluded. There are a number of considerations that need to be made and kept in mind when putting type on the Web. Many of the compromises that are made in the print world do not apply to the web medium, but others take their place.

More ≠ better

Corresponding to the growing availability of new fonts for the Web it is important to note that more fonts does not necessitate instant better typography. Fonts are assets. They may be thought of as a tool in the toolbox; a wallpaper in an interior designer’s arsenal. She might have access to a thousand different patterns and colours of wallpaper but if most of them are of a poor quality material or just lack the required pleasing grace that is required to open up and brighten (or darken as the situation merits) the space they are applied to then having another thousand more does little good.

For screen or print?

In addition to artistic concerns, many typefaces available as fonts for the Web have not been designed for web (or more accurately screen) use. Type design and typography blossomed in the print industry. There are hundreds of exquisite professionally designed and cut typefaces and families available for all types of print work, but many of them have not been readied for use on a screen. Good fonts that were designed or have been carried across to the digital world have been carefully optimised to render perfectly on a pixel screen. This optimisation is known as hinting and good web fonts subsequently have good hinting tables.


A digital font is data, and large fonts, i.e. ones that have a large glyph set covering a large character range will begin to become sizeable assets for the user agent to download for rendering. Two techniques are used here to reduce the size of font assets to make them smaller thus reducing network latency.

The first technique is called sub-setting, and is a process of removing glyphs for characters from a font file that are not used. Imagine a great high-quality superfamily with fantastic language support that also boasts additional historical ligatures, various extra stylistic sets, swashes, small-capitals, and more. A single font for even just the roman of this family could exceed a 1024 kB. If none other than ASCII, Latin 1, Latin Extended-A, and Latin Extended-B is needed (which covers all Western European Languages with a bit of wiggle room) there are a lot of unused characters for which glyphs are downloaded superfluously.

Sub-setting can be done in a font editor (such as FontForge, the free software font editor). Simply open your font, select unused character blocks and delete them; save — make sure you keep a copy of your original though.


The second technique is compression. Compressing font asset is much like compressing files to reduce the size of email attachments. Through compressing font files we can further reduce latency and network traffic. This operation is done server-side, compressing various assets that the user agents requests which upon download are decompressed on the fly and used to render the web page.

The two most popular methods are through external extension modules to the Apache web server; mod_deflate and mod_gzip. It is likely that your web hosting service will provide support for at least one of these (if not it is a worthy request to make — after all lowering their latency and traffic is in their own operational interest).

If you find yourself using Microsoft’s IIS there is a HTTP Compression setting that can be enabled and tuned.

Configuring mod_deflate

Once installed and enabled we can configure mod_deflate in our .htaccess file:

# Compression using deflate
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css

<FilesMatch "\\.(js|css|html|htm|php|xml|txt|otf|ttf|eot|svg|woff)$">
    SetOutputFilter DEFLATE

In FilesMatch list the file extensions for which files mod_deflate should compress.

Configuring mod_gzip

Similarly mod_gzip can also be configured in the .htaccess file:

# Gzips content if possible
<IfModule mod_gzip.c>
    mod_gzip_on Yes
    mod_gzip_dechunk Yes
    mod_gzip_item_include file \.(html?|txt|css|js|php|pl|otf|ttf|eot|svg|woff)$
    mod_gzip_item_include handler ^cgi-script$
    mod_gzip_item_include mime ^text\.*
    mod_gzip_item_include mime ^application/x-javascript$
    mod_gzip_item_include mime ^application/json$
    mod_gzip_item_include mime ^application/$
# There is no content-type for OTF yet, so we can get away by just
# listing the extension in the mod_gzip_item include file listing.
# For the sake of being good I have added the vendor-specific
# IANA content-type for EOT.
mod_gzip_item_exclude mime ^image\.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
    mod_gzip_send_vary On

Just like mod_deflate’s FilesMatch using mod_gzip_item_include file we can list the file extensions for files that mod_gzip should seek to compress. The content types can also be listed via the mod_gzip_item_include mime lines by notating the IANA media types as done for the vendor-specific EOT

You can test how well compression is performing through a variety of browser developer plugins or by using Mark Nottingham’s REDbot, a robot that checks HTTP resources for common problems and pitfalls. For example, when checking REDbot notes via the Content-Encoding that mod_gzip is in use. When checking the assets we can see that 84% of the original size of the page (when decompressed) is saved through the use of mod_gzip, with detailed figures for the various assets.


FInally we can also cache our font files reducing both latency and network traffic. Caching allows us to inform the user agents that access our site and download our assets that some of the assets are unlikely to change in the foreseeable future, and as such downloading them again when accessing out site at a later stage will be a waste of time and data — just store (‘cache’) these assets in the user agent’s cache locally. Assets that would be unlikely to change would likely include stylesheets (.css files), JavaScript files for site functionality (.js script files) and of course font assets.

We can cache various assets via the .htaccess file by again selecting a range of content types with FilesMatch and then setting a maximum time that these assets should be cached by user agents before downloading the asset again (to ensure cached copies remain updated). Note: the max-age time is set in seconds (here 2592000 seconds = 43,200 minutes = 720 hours = 30 days).

# Cache following file types for one month
<FilesMatch ".(js|jpeg|jpg|...|otf|ttf||eot|svg|woff)$">
    Header set Cache-Control "max-age=2592000"

And that’s it!

Now empowered to apply custom fonts onto the Web either self-hosted or via a web font licensing and hosting service be sure to look out for the second article in the series on styling that freshly set type all pretty.

This article was originally written by me for, and published on — Getting Type to the Web. It has been been republished here with permission.

For referencing: permalink to this article.