As Cai notes, the underlying cause of this bug is that the @font-face
rules in the Stack Exchange style sheet are broken according to the W3C spec, which clearly states (emphasis mine) that:
For OpenType and TrueType fonts, this string is used to match only the Postscript name or the full font name in the name table of locally available fonts.
The full font names of the bold and italic faces of Open Sans are "Open Sans Bold" and "Open Sans Italic" (and their respective PostScript names are "OpenSans-Bold" and "OpenSans-Italic"), so the string local(Open Sans)
, as used in the Stack Exchange style sheet, will (on conformant browsers) never match either of them. In the best case, this simply leads to the fallback web fonts being used; in the worst case, it may cause the wrong (i.e. not bold/italic) face to be picked instead.
That said, the reason why this bug seems so hard to diagnose is that triggering the "worst case" above requires an odd combination of circumstances:
First of all, the user must obviously have Open Sans installed locally; otherwise the correctly specified web fonts will simply get used.
Second, either the user's browser or their copy of the Open Sans font must be buggy in a way that causes the local(Open Sans)
name to incorrectly match the regular face of the font (rather than failing to match at all, as it really should).
So far, I've found two ways to trigger the second condition:
There are several different versions of Open Sans Regular floating around on the web. The one currently downloadable from Google Fonts has the full name "Open Sans Regular" (and the PostScript name "OpenSans-Regular"), the version string "Version 1.10", the unique font ID "1.10;1ASC;OpenSans-Regular" and the version number 72155. This version does not trigger the bug on conformant browsers.
However, the version of Open Sans Regular available from many other sites (such as 1001 Fonts, to name just one example) instead has the full name "Open Sans" (and the PostScript name "OpenSans") without the "Regular" suffix. Confusingly, this version also carries the version string "Version 1.10", but it has the unique ID "Ascender - Open Sans Build 100" and the version number 72090. This version does have a full name matching local(Open Sans)
, and thus triggers the worst-case behavior on conformant browsers such as Firefox.
Separately, Chrome (and possibly other browsers based on the Chromium codebase) suffers from a known bug where it incorrectly matches local()
against the family name instead of the full font name. Thus, having any version of Open Sans locally installed will trigger the worst-case behavior on Chrome.
Either way, to fix this bug, the SE style sheet should be fixed so that it correctly specifies the full name (and the PostScript name) of each local font face in local()
. Here's an example of the correct syntax, courtesy of Google Fonts:
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans Regular'), local('OpenSans-Regular'), url(...) format('woff2');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
src: local('Open Sans Bold'), local('OpenSans-Bold'), url(...) format('woff2');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 400;
src: local('Open Sans Italic'), local('OpenSans-Italic'), url(...) format('woff2');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 700;
src: local('Open Sans Bold Italic'), local('OpenSans-BoldItalic'), url(...) format('woff2');
}
(Webfont URLs and extra rules for non-Latin subsets omitted for brevity.)
Note that, due to the aforementioned Chromium bug, using this corrected CSS will cause current Chrome versions to never make use of any locally installed copy of Open Sans. However, this is still better than the current behavior, where having a locally installed copy of Open Sans will break bold and italic text on Chrome.
Ps. One possible workaround for this Chrome bug might be to get rid of the local()
font sources entirely and rename the CSS font family defined by the @font-face
rules to some custom name like "Open Sans (WOFF)", like this:
@font-face {
font-family: 'Open Sans (WOFF)';
font-style: normal;
font-weight: 400;
src: url(...) format('woff2'); /* NOTE: no local() here! */
}
@font-face {
font-family: 'Open Sans (WOFF)';
font-style: normal;
font-weight: 700;
src: url(...) format('woff2');
}
@font-face {
font-family: 'Open Sans (WOFF)';
font-style: italic;
font-weight: 400;
src: url(...) format('woff2');
}
@font-face {
font-family: 'Open Sans (WOFF)';
font-style: italic;
font-weight: 700;
src: url(...) format('woff2');
}
Any font
or font-family
properties referencing Open Sans elsewhere in the style sheet could then be changed to look something like this:
html, body {
font-family: 'Open Sans', 'Open Sans (WOFF)', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 13px;
line-height: 1.30769231;
color: #242729
}
In have not yet tested this, but in principle this should make Chrome (as well as other, conformant browsers like Firefox) prefer to use the locally installed Open Sans font, if any (but without triggering the broken local()
matching), and only fall back to the custom "Open Sans (WOFF)" family if no local Open Sans is found. If the webfont cannot be downloaded either, the browsers should then try the other listed fallback font families.
Or, alternatively, SE could simply decide that webfonts are the future and drop local fonts (except for the generic serif
/ sans-serif
/ monospace
fallbacks) from their style sheet entirely. While this would IMO be a suboptimal solution, it probably would be the path of least effort.
After all, the fact that this bug has not been reported more often than it has been kind of suggests that very few SE users (or at least, very few people using SE on Chrome) actually have Open Sans installed locally, and that the webfont is working fine for most people.
(That said, it should be noted that Open Sans and other webfonts are currently only used on a handful of smaller SE sites. The really big sites like SO don't currently use @font-face
or webfonts at all, and introducing them to those sites might create a whole new set of bandwidth issues.)
BTW, assuming that no unexpected issues turn up, the next version of my SOUP user script / browser extension will include a workaround for this bug that simply overrides the broken SE @font-face
rules with those from Google Fonts. It's already available for testing in the SOUP development branch, and seems to be working fine (with the caveats regarding Chrome noted above).