Link to

Fork me on GitHub

Monday, January 14, 2013

Webkit's -webkit-font-smoothing can make you fat

In a recent set of changes to our user interface, we came across rendering issues that were driving us bonkers: how could two pieces of text with the same color value appear to have different weight? It turned out the culprit was font smoothing.

The font-smoothing CSS property is nothing really new at this point and I'm betting most developers leave it at its default anti-aliasing setting: auto. In our case, we wanted a more crisp styling of text with Webkit-based browsers and so we used the vendor-specific property -webkit-font-smoothing. (A good explanation of the available attribute values is in a 2012 post by Tim Van Damme.) The trouble was that our wish to use "antialiased" as the font smoothing value was being overridden by a greedier button style that defaulted to auto—which, on Webkit browsers, becomes subpixel-antialiased.

What is the difference? Check out the following three lines of Webkit-styled text:

The first line has -webkit-font-smoothing set to none and it appears barely legible. The second line is using antialiased, and the third subpixel-antialiased. See how the third line appears not only darker but thicker? (A really good, detailed article on how anti-aliasing and subpixel anti-aliasing works was written by Krzysztof Szafranek. Typekit also has some good info.) Let's magnify those pixels to see the true difference in the rendering strategies:

  • Again, the first example doesn't use anti-aliasing so as the letterforms are drawn to the screen pixels are either turned on or turned off resulting in hideous jaggies.
  • In the second example the renderer takes into account the partial filling of the pixels across the pixel boundaries and so it does a kind of averaging with the color of the font and the color already on the screen.
  • And the third example is much more complicated but it uses the fact that pixels are made up of tiny Red, Green, and Blue stripes, and the renderer tries to do the same kind of averaging but taking into account the pixel may fall into a partially-Red, partially-Green, or partially-Blue sub-pixel. As you can see, on the left side of the "T" the letterform is slightly falling onto that Red sub-pixel, and if you look just to the right of the "i" there's a slight bleed into the Blue sub-pixel.

What does this ultimately mean? Possibly that your fonts could have a little more screen coverage (due to the bleeding into the sub-pixels) and, probably more importantly, your colors could be slightly off. In our case the subpixel anti-aliasing made the deep blue text feel more weighty and slightly more purple.

Try it out for yourself in Chrome, Safari, or another Webkit-based browser: