Soft hyphen bug in Webkit

Recently a Fontdeck customer asked for help regarding a problem he was having with a soft hyphen. As I investigated further, it revealed a peculiar bug in Mac-based Webkit browsers, including Safari and Chrome. The bug may also be present in other operating systems, but for reasons that will become apparent, it doesn’t manifest itself.

What is a soft hyphen?

Soft hyphens enable you to manually insert hyphenation points in words, predating the hyphenate CSS property. Thus a soft hyphen is a hyphen which is only displayed when a word is split across two lines. Put another way, the character says ‘hyphenate here if you need to’.

Soft hyphens can be represented by the HTML entity ­ or the Unicode character U+00AD (in the Latin-1 Supplement range between ¬ and ®).

What is the bug?

I’ve written about soft hyphen bugs before, but this is different: under some circumstances, when using webfonts (any webfonts, not just Fontdeck) Mac Webkit browsers will display the missing glyph￰ symbol where the soft hyphen is placed.

![The ￰missing glyph symbol displayed where the soft is placed](/images/shy-screenshot.png)
Screenshot of the soft hyphen bug in Chrome/Mac v36

I’ve created a test page to illustrate exactly when this occurs. In essence it only happens with sans-serif webfonts of font-weight 100 or 200. Heavier weights, serif and monospace fonts are unaffected. It also only happens if the default sans-serif font in your browser is Helvetica (the factory setting).

What’s going on?

I’m not exactly sure what or why this is happening, but it seems down to a problem with the font fallback mechanism and a bug in Helvetica Light.

The Mozilla Developer Network has this explanation about font fallback:

The font-family property specifies a list of fonts, from highest priority to lowest. Font selection does not simply stop at the first font named in the list that is on the user’s system. Rather, font selection is done one character at a time, so that if an available font does not have a glyph that can display a character needed, the later available fonts are tried.

In my examples, the web font I’m using is Aperçu Light. Like most web fonts – indeed most fonts – it doesn’t have a soft hyphen glyph. So when the browser comes across one in the content, it needs to go down the font stack to find a font which does contain a soft hyphen.

In the case of font-family: "Apercu Light", sans-serif the browser tries to render a soft hyphen from the Helvetica Light OS X system font. Helvetica Light does seem to have a place mapped for a soft hyphen, yet it is rendered as a missing character￰ glyph, indicating the character is not in fact available.

Chrome Developer Tools

This is where is gets peculiar

If we swap Aperçu Light for Helvetica Light, as in font-family: Helvetica, sans-serif then Webkit seemingly recognises the problem with Helvetica Light and decides to use a soft hyphen from Lucida Grande, which renders correctly.

(You can tell this by selecting the text and looking at the Computed tab in Chrome’s Developer Tools.)

If we now insert Helvetica into our web font stack, as in font-family: "Apercu Light", Helvetica, sans-serif, Webkit doesn’t resort to Lucida Grande, it still tries to render Helvetica Light’s broken soft hyphen.

There is a fix

And that fix is Arial! Stick Arial somewhere appropriate in your font stack and soft hyphens render as required, eg. font-family: "Apercu Light", Helvetica, Arial, sans-serif. Other system fonts work too, notably the afore-mentioned Lucida Grande, as do Helvetica Neue and Avenir Next, but curiously Avenir suffers the same problem as Helvetica.

And since Blink has branched off from Webkit but still contains the issue, I’m going to have to post the bug in two places.