One of the features we wanted was automatic “smart quotes”. Instead of the bland vertical quotes you often see on a computer “•”, we’d replace them at render time by fun curvy quotes “•” to make the text more alive.
I’d known for a while that OpenType was capable of some processing during font rendering, and so I set myself the challenge of implementing smart quotes in the font file itself. To cut a long-story short: it works, and it’s easy to modify an existing font to support it.
The first trick to getting fancy font features working on the web is to set up your
font-feature-settings CSS property (actually
-moz-font-feature-settings). This also works in IE 10+, but surprisingly, is not available in Safari.
The value of this property is a list of quoted four-letter OpenType features followed by a number for its value.
The most essential feature to enable is
"kern", which enables proper kerning. It’s also nice to enable
"dlig" which control the use of ligatures. Hover over the following image and notice how the ugly space between the
nw of Fanwood is tightened, and how the messy
fl is replaced by a ligature.
Under the hood each OpenType feature is a set of pattern matches: when a certain sequence of glyphs occurs you can substitute a new glyph into place, or change its position. The OpenType Cookbook is a good reference for the syntax used, which is supported by most font editing tools and processed by the ADFKO.
The patterns are very simple, but you can use a few techniques to implement surprisingly complicated substitutions.
- You can specify an
ignorerule to skip a rule.
- You can define character classes to group characters together.
- (I haven’t needed this yet) You can group rules into lookups, where only one rule from each lookup is used.
Starting small, we can implement a simple rule to replace exactly two hyphens (–) by an em-dash (—):
To implement smart-quotes we need to be able to tell if a quote is at the start of a line. We can approximate this by defining the character class
@All which contains all the glyphs in the font, and then using
@All to catch any quotes that happen after a character. Quotes that don’t happen after any character are at the start of a line.
Because there was no pre-defined OpenType feature name for smart
quotes, I’ve added it to the font as
"ss01" or Stylistic Set 1.
You can see the effects of the full
by hovering below:
Inspired by Typeset, I wanted to see if I could also implement hanging punctuation. This gives the left-margin a strong vertical line by having punctuation marks extend beyond it. Once I had the substitution rules and the character classes set up for the smart quotes, this turned out to be simple:
The positioning rules move the left and right of the glyph independently. The number
421 comes from looking at the glyph for a curvy left quote and taking its width including some spacing. I only needed to look at the curly left-quote, because the
"opbd" feature is defined after
"ss01" and so all the plain quotes have already been replaced at this point.
This technique only works for punctuation on the left, but as most text on-screen is set with a ragged right margin, you don’t normally need punctuation that hangs out to the right.
More work could be done, Typeset moves “Y”s, “V”s and “W”s out a little too, but this served as a proof of concept.
You can download my hacked version of Fanwood Text from GitHub, or preview it. I used Glyphs to open the existing Fanwood font and add a new feature. If you use a different app, I’m sure you can re-use the syntax, but the UI might be more or less confusing.
If you’re still reading and would like to chat about fonts, or work on a beautiful email client, please email me.