EJS logo

Advanced web typography: A recap on OpenType features

How time flies! It was now almost two years ago that I wrote my ’Tomorrow’s Web Type Today’ series of blog posts ( 1, 2, 3, 4) and did a talk based on their content at the Ampersand and TYPO Berlin conferences. (You can still watch the video from the latter event, if you’re interested.)

This week I’m in the process of preparing for a new talk at TYPO SF ( tickets are still available, by the way) and although I’m focussing on topics such as kerning and responsive typography (accompanying posts will follow in the next couple of days), I thought it was worth returning to the topics I covered before; mainly as a refresher, but also to see what’s changed since then.

In short, not much has changed, and in a way that makes me a little sad. Two years ago it felt like things were changing almost daily and that this bleeding edge stuff was, well, bleeding edge. There’s not much to report in terms of new features, and although browser support has improved, progress seems to have slowed and the varying levels of support are still pretty confusing. So let’s try and demystify some of this.

The four areas I covered previously were:

  • ligatures,
  • small caps and old style numerals (with subsets for polyfilling),
  • swashes (with subsets again), and
  • stylesets.

Recap: ligature support

Overall support for standard ligatures is now very good and easy to turn on by using text-rendering: optimizeLegibility; (they’re turned on by default in Firefox). However, that’s non-standard code (EDIT: and, as pointed out by Chris Adams in the comment below, text-rendering: optimizeLegibility; has also been known to cause issues), and it’s a far better idea to use the standardised and more powerful font-feature-settings property. Support for this property is actually pretty well supported overall, but the various features it controls (ligatures, kerning, stylesets, etc.) varies from browser to browser, so it’s perhaps not as straightforward as you might think from looking at a table on caniuse.com. EDIT: Ligatures, fortunately, do have good support, and although Safari 7 on both OS X and iOS doesn’t support font-feature-settings , the browser does have support for ligatures, contextual ligatures, and required ligatures, because they’re enabled by default — just not discretionary ligatures. (Weirdly, Safari 6 supported font-feature-settings for enabling ligatures, contextual ligatures, and required ligatures.)

For a more future-facing but generally unsupported way of enabling ligatures, refer to font-variant-ligatures in the ‘CSS Fonts Module Level 3’ spec, last updated in October 2013.

Recap: small caps & old style numerals support

Like all of the features I’m covering here, there are plans in the ‘CSS Fonts Module Level 3’ spec to give us very specific, high-level controls over OpenType features, but because it’s very much a work in progress and support is highly experimental (read: mostly unusable at the time of writing), we stand a much better chance by using the font-feature-settings property. The spec defines it as ‘low level’, but I think that’s misleading — it’s certainly a lot more high level than text-rendering: optimizeLegibility; and you can get pretty granular with your control.

For example, excluding the necessary vendor prefixes (see the ‘So, to summarise…’ section, below), here’s how we can turn on small caps and old style numerals:

font-feature-settings: 'smcp' 1;
font-feature-settings: 'onum' 1;

Pretty simple, eh? In my example from a couple of years ago, I used subsets to polyfill the lack of support for these features (see the subsets recap, below).

For the aforementioned future-facing but generally unsupported way of enabling small caps, refer to font-variant in the ‘CSS Fonts Module Level 3’ spec, last updated in October 2013.

Recap: swashes and stylesets support

Guess what? Implementing swashes and stylesets is exactly the same: we use the font-feature-settings property. But remember that although browser support is good for the overall property, each specific feature has its own level of support. By and large, the rule of thumb should be to test across multiple platforms and browsers, and use a subset to ‘cheat’ your way around poor support.

For a more future-facing but generally unsupported way of enabling swashes, stylsets, and stylistic alternates, refer to font-variant-alternates in the ‘CSS Fonts Module Level 3’ spec, last updated in October 2013.

Recap: subsets

As mentioned above numerous times, it’s possible to polyfill the absence of support for bleeding edge features by using subsets instead. Subsets are an idea that come from the pre-OpenType age of fonts: to utilise certain features, you literally serve up a different file that contains only those extra features you need (such as swashes, old style numerals, etc.). A good example is something like Acta Poster Swashes, which I used for the ‘S’ and ‘W’ glyphs on the swashes post.

So, to summarise…

A subtle but relatively important change since writing my original posts has been that the font-feature-settings syntax has become standardised and most people no longer seem to worry about using the outdated, non-standard syntax required for older versions of Firefox ( -moz-font-feature-settings: "liga=1"; ). Also, assuming you use vendor prefixes, there are a lot of features you can get working in most major browsers. IE10+ support is great as long as you’ve got the oft-omitted -ms- prefix in there. (Opera’s -o- prefix, meanwhile, is relatively useless at the time of writing.)

Here’s the CSS generated by the wonderful Typecast for standard ligature support:

-webkit-font-feature-settings: 'liga' 1;
-o-font-feature-settings: 'liga' 1;
-moz-font-feature-settings: 'liga' 1;
-ms-font-feature-settings: 'liga' 1;
font-feature-settings: 'liga' 1;

For other OpenType features, you’ll be pleased to know that the naming conventions follow those used in font files’ tables, such as:

  • Discretionary ligatures: "dlig"
  • Lining numerals: "lnum"
  • Old-style numerals : "onum"
  • Small caps: "smcp"
  • Swash alternates (with the index number): "swsh" n
  • Stylesets (01–20): "ss01–20"

However, regardless of the particular feature or browser support, using OpenType on the web today still essentially comes down to these four key considerations:

Consider the typeface: does the actual typeface contain swashes, ligatures, and the like?

Consider the font file: is it actually an OpenType file being served? Even if it is, are the extra glyphs you need included in that particular font? Do you need to adjust any settings to export additional characters? (In Typekit, that involves choose ‘all characters’ in the Kit Editor.)

Consider the browser: which features does it support? Remember: support can differ massively between version numbers and operating systems. Do you need to polyfill support by adding special characters via subsets?

Consider the user: will the design break if certain OpenType features are missing? Does the type actually look that good? Even generous feature support is subject to poor type rendering on some operating systems.

For further reading, I thoroughly recommend this excellent (but slightly outdated) article on the Typotheque blog by Gustavo Ferreira, and this OpenType primer on the Fontdeck blog by Rich Rutter.

Now that we’ve recapped all of that stuff, I’ll be exploring some new topics in my next posts. Tomorrow’s will be on kerning!