My (just-discovered) workaround to the WebKit letter-spacing bug

Update (5/29/2012): Upon working further with the project that formed the basis of this post, I discovered that my solution did not work, or at least, no longer worked. It’s not uncommon as I get deeper into a project with a large CSS file that there are subtle, inadvertent effects of the various CSS properties that get added along the way. Looking back now, I can’t determine for sure whether my solution did once work with the simpler version of the site, and something else I added later counteracted it, or if I was just too eager about a solution to realize it never quite worked in the first place. As a result, I had considered deleting this post entirely, but I have decided to leave it live, to further the discussion of the topic, or at the very least to serve as a monument to my challenges.

WebKit, the rendering engine “under the hood” in both Safari and Chrome, has a known issue handling the CSS letter-spacing property at certain small increments, and at certain font sizes.

Specifically, if defining letter-spacing in increments smaller than 1px or 0.1em, it seems to just ignore the property altogether… except at larger-than-default sizes.

I typically use em or % these days to define text sizes in CSS. So in my situation, I’ve found that my letter-spacing: 0.05em works if I also specify font-size: 125% (or larger), but if I have font-size set to 100% or less, the letter-spacing gets ignored.

Typically, after loading reset.css, I set a baseline font size for the document with body { font-size: 100%; } (or some size… actually it’s usually 80% but these days I’ve been leaning towards larger type).

I decided to play around with this a bit to see if I could resolve the letter-spacing issue, and I found a nice, easy solution that works at least for the particular site I’m currently testing it on. Your experience may vary, depending on how your HTML is structured and how complex your design is.

Here’s the solution:

body {
  font-size: 125%;
  letter-spacing: 0.05em;
  line-height: 1.3em;
}

body>* {
  font-size: 85%;
  line-height: 1.3em;
}

You may want to adjust the exact values of font-size to suit your needs. (And, yes, I’m aware that mathematically 125% and 85% don’t cancel each other out, but they’re close enough for my purposes.) It’s important to include the line-height property in body>* to define your target line height; otherwise your lines will be too far apart. Set it to whatever your ideal value is. (I usually prefer line-height: 1.5em personally, but for larger type, as on the site I’m currently working on, it gets too spaced-out.)

So what’s going on here? Well, strangely, it seems WebKit can actually render smaller type with line-spacing less than 1px or 0.1em just fine, but it won’t unless somewhere in the “cascade” the type has been defined as being a certain amount larger than 100%. I don’t get it, but until the bug (which it seems clearly to be after all of this) gets fixed, at least this seems to be a reasonably clean workaround.

It’s very important that you use body>* and not just body *. If you don’t know why, well… try it out and see. (The upshot: we’re applying a uniform scaling-down across the board on all elements directly under body, which is practically the same as just defining our target font size directly on body itself, but with the benefit of working around the letter-spacing bug.)

Note: I have only tested this using em as the unit of measure for letter-spacing. I’m aware of the issue with px as well, but I’m not sure this solution will work for that. But… really… just use em instead!

7 thoughts on “My (just-discovered) workaround to the WebKit letter-spacing bug

  1. Just came across the same issue and Google turned up this post. Very annoying that it should ignore letter spacing! At least I know what it is now though, thanks.

  2. May I suggest posting the update at the top of the article? I find it very annoying to read through the entire article only to find that I have wasted my time.

  3. A good point, which I have taken. But may I suggest displaying a little more courtesy in your comments? I did not force you to read this, nor did I guarantee a solution to your problem.

  4. Awesome job here, room34. You were absolutely right, and your time in writing this blog has perhaps saved a life (as I was deliberating various methods of suicide over my failing attempts to solve letter-spacing rendering in Chrome / Safari). . .

    I had already defined font-size: 100%; for my body, and letter-spacing defined in em’s with a fallback to pixels for my p tags, and a simple change of:

    body { font-size: 101% }

    …made all the difference. Suddenly everything looks as is should in Safari / Chrome.

    So THANK YOU! Oh, and blarg, please go step in front of a fast-moving bus.

  5. Thank you SO MUCH for this! Far from being a waste of time (*cough “blarg” cough*), this is the best solution out there for this bug. I used the above code for my body text, and applied custom font-size and letter-spacing values (in ems) to my various headings (the values come out a bit smaller than usual to achieve the same results). After some fiddling it’s close enough to being perfect when I test it in BrowserStack. Some values won’t work consistently, but that’s where the fiddling comes in. Again THANK YOU.

  6. Sorry I’m not going to be specific but I’ve always found -0.0x em or pt works in Chrome when specifying font-size in pixels…but it doesnt seem to work for all numbers. Each browser seems to register numbers at different points so it’s about findintg the commopn place between each browser or sparating styles for various browsers to achieve the same results

  7. Thanks a lot man,……done good job…i have problem in chrome, it continous more days but now your information is very useful.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>