Tuesday, February 8, 2011

Quick Fix for Ugly Font Rendering in Windows Browsers

This post presents a quick fix for the broken font rendering problem on Windows browsers. The quick fix disables @font-face CSS directives on Windows, using JavaScript. The next sections present the code, and describe the motivation behind this solution.

Code

All the code is standard JavaScript, except for $(window).load, which is jQuery's way of hooking into the onload DOM event. Replace that with your framework's specific method, if you're not using jQuery.

Motivation
I got bug reports stating that some fonts I chose look horrible on Windows. I looked into the problem, and saw that most downloaded fonts look much worse on Windows than on the other OSes. While playing with font choices, I also noticed that default fonts look decent, and I concluded that I shouldn't be downloading fonts via @font-face on Windows.

I didn't want to degrade the experience for all my other users, so taking out the @font-face directives from CSS was out of the question. Because of the way that Rails handles CSS optimizations, I couldn't produce a different CSS stylesheet just for Windows clients, so I decided to remove the @font-face directives in JavaScript.

Conclusion
The JavaScript above can be dropped into any Web application that uses @font-face, regardless of server-side language or framework, and it will make life better for Windows users. However, because it is JavaScript, Windows users may notice a viewport re-paint while JavaScript changes the page's stylesheet. This will only happen on the first visit to the site, as long as your Web application serves correct caching headers for the JavaScript and CSS.

The code is also very bad programming practice. It is entirely possible that Windows 2020 will have better font rendering, or that browser providers will take matters into their own hands. If that happens, you will have to do feature detection on the font rendering engine.

Thank you for reading this far! I hope that you have found the post useful, and I'm looking forward to your questions and suggestions for improvements!

2 comments:

  1. Well why not just add the operating system as an class to the html element like modernizr does?

    i. E.:

    if (/win/i.test(navigator.platform)) {
    $(html).addClass("win");
    }

    and then just overwrite the font-family property by defining it in your css file:

    .win { font-family: Garial, Fckdana, Times National Socialist !important; }

    Should be better in terms of performance and coding practice (and you can use it for other oss-specific hacks later on).

    Haven't had a look at Windows yet, but it seems like on webkit there is an font-smoothing property which controls the anti-aliasing of fonts (Chrome and Safari).

    http://maxvoltar.com/archive/-webkit-font-smoothing

    Cheers

    Simon

    p. S.: Sorry couldn't find the correct tags for syntax-highlighting.

    ReplyDelete
    Replies
    1. @Simon, your solution is more elegant, but I'm not sure it's faster. Thank you for posting it here!

      Your solution seems to trigger a CSS reflow for the entire document, after the body tag changes. My solution also triggers one CSS reflow, by removing the @font-face rules, so they seem on par performance-wise. Your solution does less work on the DOM, but my solution doesn't add an extra rule that the CSS engine would have to consider on every reflow.

      I don't understand browser performance very well. I got most of my information from the link below. Please correct me if my assumptions are wrong!
      http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/#The_flow_of_constructing_the_tree

      I think the right approach depends on your programming style and circumstances. I don't test on Windows (or for Windows) regularly, and I think that yanking the CSS rules makes it less likely that something will break due to CSS specificity bugs. On the other hand, your solution makes it easy to check that the CSS works correctly, by adding the "win" class using developer tools.

      Last, it seems like -webkit-font-smoothing doesn't work on Windows.
      http://christophzillgens.com/en/articles/-webkit-font-smoothing-reloaded

      Thank you for making me look, though! I'm always glad to learn more CSS!

      Delete