Chrome on Windows can't render Roboto Light

Published

We've been having some problems with the changes we made to our site's design, specifically our choice of the Google Android font Roboto Light for the main body text. We've deployed it as a web font, and it seemed to work everywhere just fine. Until, that is, we got reports that it wasn't rendering properly in Chrome on Windows. Ironically, the only browser that can't render this font is made by the same people who made the font itself.

Some of the letters have pieces missing, such as the horizontal bit in the middle of upper and lowercase ‘E’, and the cross-bar on top of a lowercase ‘t’. Em-dashes were completely invisible, and italics was a complete disaster.

Apparently Chrome's problems on Windows stem from the fact that it's based on WebKit (actually now a forked version they're calling Blink), and that still uses an old Windows API to do font rendering, rather than something newer called DirectWrite. Chrome on Linux and MacOS aren't affected. Anyway, they're working on fixing this, and it sounds as though it'll be OK in Chrome version 37.

I think we've found an acceptable solution for now, until new fixed Chrome gets into the wild. I've set up some browser sniffing JavaScript code to detect the exact condition we want (only Chrome, only on Windows, and only versions earlier than 37), and when the browser meets those conditions, it adds a disable-roboto class to the root <html> element. Then it's a simple matter to override the lists of fonts in our font-family properties when that class is present.

This browser sniffing is usually considered to be a bad way of doing things, since it's dependent on non-standardized aspects of a browser's implementation to distinguish one from another. Most of the time, if you want to conditionally turn on some JavaScript—such as a polyfill—then feature detection like that done by the Modernizr library is much less fragile. This Roboto font rendering situation though is one of those times when I actually do need to know whether the user is running a specific browser.

In case it comes in handy, here's the JavaScript code I came up with, after some poking around on Stack Overflow:

(function() {
    // Disable Roboto font on Chrome on Windows, because Google can't
    // render their own font properly.
    var is_opera = window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
    var is_chrome = window.chrome && !is_opera;
    var is_windows = navigator.appVersion.indexOf("Win") !== -1;
    var match = navigator.userAgent.match(/Chrom(?:e|ium)\/([0-9]+)\./);
    var ver = match ? parseInt(match[1]) : 0;
    if (is_chrome && is_windows && ver < 37)
        document.documentElement.classList.add("disable-roboto");
})();

I can't use jQuery to add the class, since it won't be loaded until the end of the page, and I want this snippet in the <head> to avoid a FOUC. Luckily I can rely on the .classList.add method as an alternative to jQuery's .addClass method, since that line only has to work in Chrome. According to the Mozilla Developer Network page on the .classList thing it was added way back in Chrome 8, so it should be reliable.