Divya Manian

RSS Feed Youtube Channel Github

Fake Bolding of Web Fonts

If you are like me, you would have been (ab)using Google Web Fonts for your custom font needs. In which case, you most certainly would have tripped on this problem: Faux Font bolding.

Most browsers synthesize the bold weights of fonts that do not posses a bold weight. For example, the font ‘Helvetica Neue Light’ does not have a bold version available. If you use font-weight: bold with that font, browsers will artificially create a bold weight and render it like this

Rendering of fake bold on helvetica neue light

The Problem

Now, this problem is exarcerbated when used with web fonts, especially the free open source fonts that are served from a service. Google Web Fonts, for example, serves slab fonts like so:

@font-face {
  font-family: 'Erica One';
  font-style: normal;
  font-weight: normal;
  src: local('Erica One'), local('EricaOne-Regular'), url(<font url>) format('woff');

What this code declares to a browser is: “Hey, this is the least weight available for this font called Erica One. So, if anyone wants a heavier weight, you need to synthesize it just like you would do it to local fonts.”

Now, the problem occurs if you only want to use this font for your headings. By default, browsers apply font-weight: bold to all headings. But the browsers need to obey the font-weight descriptor that is used in the @font-face rule above! This means, they will try to fake the bold weight of the already-heavy weight Erica One. Alas, the method used for synthetically generating the bold weight is not specced, so each browser does its own magic! Here is the normal weight of a typical slab web font(Google Web Font Ultra) overlaid on top of the synthetic bold generated out of it (here is the code used to generate this graphic):

Image of the synthetic font

How to solve this?

There are two ways to resolve this:

If you are in control of the @font-face rule

Then the trivial solution is to add a font-weight: bold declaration which tells the browser “This font is a heavy slab font intended only to be rendered as a bold. Dont create synthetic bold versions for this”. This would work universally across any selectors irrespective of what the font-weight value is for them. This is the recommended solution.

Unfortunately, this won’t quite work if you are using one of the recommended options of Google Web Fonts, as you have no control over the font-weight descriptor in the @font-face rule that Google outputs. So we now move to Option 2.

Set font-weight: normal to all selectors using the slab font

This is the trivial solution if you are using font services whose @font-face rule you do not have control over. The way I would do this, in Sass is to define it in this manner:

.slab-serif {
  font-family: 'Ultra', serif;
  font-weight: normal;

h1 {
  @extend .slab-serif;

If you are using just CSS, then ensure everytime you set the font-family to be that slab web font you use a font-weight: normal declaration. Aha, this is actually what Google Fonts recommend in the sneaky little box to the right.

In any case, if you can avoid exposing your users to horrific fake bolding, you should. And that is the point of this post: to remind myself to never ever have browsers fake the weights of web fonts.

Note: Here is Chris Coyier’s take on it.