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!

@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!

Short Bio

Victor Costan got infected with a passion for coding at the age of 10, and proceeded to earn a M.Eng in Computer science from MIT. Victor also holds a B.S. in Management that he pursued as he fell prey to the belief that great software requires legions of developers manipulating bloated code bases in repetitive ways. Thanks to Paul Graham's essays, Ruby, and Rails, he re-discovered the joy of coding, and came back from the dark ways of management.

Nowadays, Victor is still crazy about building software that he can impress his friends with, but he also dreams of contributing to making coding even more enjoyable. Victor likes developing mobile and Web 2.0 applications, and occasionally enjoys building some distributed systems behind the apps. When he is not coding, you will most likely find him reading up on some new programming language or software development technique.

At times, Victor likes to pretend he's mentally sane, and can be seen catching up with friends, watching a movie, or exploring Boston.