Customizing fonts in Firefox on Linux

I recently updated my desktop machine from Ubuntu 18.04 to 20.04. (I tend to be skittish and stick to the LTS releases.) Everything went great, except that when I opened some of my go-to websites (such as GitHub), the fonts just looked… off.

Screenshot of GitHub rendered in Nimbus Sans

After some research, I learned a few things:

  1. Firefox relies on an OS-level utility called fontconfig to choose fonts.
  2. On Ubuntu 20.04, fontconfig has a default config file that automatically replaces proprietary fonts like Helvetica with free fonts like Nimbus Sans.
  3. If a web page’s CSS has Helvetica in the font-family property, Firefox will ask the OS, “Hey, do you have Helvetica?” And the OS will say, “Yep!” and serve up Nimbus Sans.

Nimbus Sans is not an attractive font to my eyes. I would have much preferred an alternative like DejaVu Sans or Liberation Sans (one of which, I’m pretty sure, is what Ubuntu 18.04 was using). So I did some digging.

Surprisingly, I couldn’t find a simple answer to “how do I tell Firefox which fonts to use on Linux?”. The fontconfig man pages are too dense to be much help. But after stumbling upon this helpful blog post, I eventually found a solution.

Create a fontconfig file

First, I created a file at ~/.config/fontconfig/fonts.conf (you may have to create the directory). Here’s mine:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
  <alias>
    <family>Helvetica</family>
    <prefer>
      <family>Liberation Sans</family>
    </prefer>
  </alias>
</fontconfig>

Basically, this file says, “If you’re trying to render Helvetica, prefer Liberation Sans instead.”

Create a test HTML page

Next, I created a small HTML page that just renders various CSS font-familys, like this:

<h2 style="font-family: Helvetica">Helvetica</h2>
<h2 style="font-family: system-ui">system-ui</h2>
<h2 style="font-family: sans-serif">sans-serif</h2>
<h2 style="font-family: Arial">Arial</h2>

If you’re curious, by default Ubuntu 20.04 will give Nimbus Sans for Helvetica, DejaVu Serif for system-ui, DejaVu Sans for sans-serif, and Liberation Sans for Arial (on Firefox 75).

Then my debug cycle became:

  1. Edit the fonts.conf file.
  2. Reload the page in Firefox (you may have to close the tab and open a new one).
  3. Open the Firefox developer tools to the “Fonts” section.

Screenshot of Firefox DevTools showing the "fonts used" section

Using this technique, I could finally get GitHub (as well as some other sites) to better suit my tastes:

Screenshot of GitHub rendered in Liberation Sans

Here is a zoomed-in before and after (Nimbus Sans on top, Liberation Sans on bottom):

Screenshot comparing Liberation Sans to Nimbus Sans in GitHub

Hopefully this blog post is helpful to someone else trying to figure out fontconfig. Good luck!

Notes

This research upended my understanding of how font-family works in CSS. I figured that if a website declares font-family: Helvetica, sans-serif, then it will fall back to sans-serif if Helvetica doesn’t exist on the user’s OS. But given that the OS can lie about which fonts it supports (and thus choose “Helvetica”), this can really change how fonts render.

Apparently fc-match Helvetica is supposed to show which font fontconfig chooses for Helvetica. This didn’t work for me. Running this command (with or without sudo) would always return “Nimbus Sans,” regardless of what Firefox was showing. Clearing the cache with fc-cache -rv also had no effect. Go figure.

Also, the Firefox font settings (Preferences → Fonts and Colors) don’t work. Well, maybe they work for choosing the default sans-serif font, but they don’t help if a website’s CSS explicitly lists Helvetica first. (As they often do, which is perhaps a testament to the Mac-centrism of most web developers. I even found this pattern in my own website’s CSS, which probably dates back to when I was a Mac user.)

Also, be aware that Chrome uses its own system for managing fonts, different from Firefox’s. If you test Chrome, you’ll get different results.

7 responses to this post.

  1. […] « Customizing fonts in Firefox on Linux […]

    Reply

    • Posted by Kenneth on May 11, 2020 at 8:16 AM

      Why not use the Installer for Microsoft TrueType core fonts < ttf-mscorefonts-installer >

      Reply

  2. Posted by godzigga on May 11, 2020 at 11:35 PM

    A few things that caused you a little bit of struggle and is the reason you couldn’t get your substitutions to work across the board.

    First, the Fontconfig README (etc/fonts/conf.d) says:

    “Each file in this directory is a fontconfig configuration file. Fontconfig scans this directory, loading all files of the form [0-9][0-9]*.conf… The files are loaded in numeric order, the structure of the configuration has led to the following conventions in usage:… Files beginning with: 30 through 39 | Contain: family substitution”

    So naming your file something like “3[0-9]-[filename].conf” (don’t forget the hyphen between the ] [)would have allowed loaded your user space .conf file to be properly loaded into the system side .conf file.

    Second, you put your .conf into “~/.config/fontconfig/” and it should have been in “~/.config/fontconfig/conf.d/”.

    Putting both of them together would mean you would have created a file at “~/.config/fontconfig/conf.d/3[0-9]-[filename].conf”. For example, mine is “~/.config/fontconfig/conf.d/31-aliases.conf”

    —–

    For your XML, adding a few things to match Fontconfig’s known/expected elements, in case the parser doesn’t know to skip the empty elements. My .conf looks like:

    Helvetica

    [PREFERRED REPLACEMENT FONT]

    —–

    You can also add additional lines to replace default font families as well: [serif] [sans-serif] [monospace] [system-ui], etc.

    —–

    “Apparently fc-match Helvetica is supposed to show which font fontconfig chooses for Helvetica. This didn’t work for me. Running this command (with or without sudo) would always return “Nimbus Sans,” regardless of what Firefox was showing.”

    It was showing Nimbus Sans because you never successfully edited the system’s Fontconfig file due to the problems above. If you fix that, “fc-match Helvetica” (or “fc-match -s Helvetica” to show the replacement preference order) will properly show your selected replacement.

    Also, you should just need to run “fc-cache” to reload the cache and you may also need to restart some applications to get them to reload Fontconfig.

    —–

    If that is still a pain in the ass and isn’t working, you can run “sudo apt install font-manager”, launch Font Manager from Dash/Terminal, click the settings cog in the title bar, click on “Substitutions”, click the left + (if necessary), enter Helvetica into the text box labeled “Enter target family”, click the right +, keep the first drop down as “prefer”, enter the name of the font you want to be substituted for Helvetica, click save in the lower right corner, run “fc-cache” in the terminal, restart Firefox/Chrome, and when you pull up your test site in any browser it will display properly!

    Reply

  3. Alias didn’t work for me.

    This did:

    Helvetica
    Liberation Sans

    Reply

  4. You can also do it in the following way-

    Click the menu button. and select Options. Preferences.
    In the General panel, go down to Language and Appearance.
    Under Fonts and Colors, use the drop-down menus to select the font and font size of your choice.
    Close the about:preferences page. Any changes you’ve made will automatically be saved.

    Reply

  5. Thank you for the post! The provided instructions didn’t work for me, until I did two things:

    Instead of alias I used alias binding="same" (please imagine angle brackets around these; I didn’t put them in because I saw other comments missing markup and there’s no preview to figure out how I should escape the brackets), which is helpfully not documented in https://www.freedesktop.org/software/fontconfig/fontconfig-user.html, but I saw this in /etc/fonts/conf.d/61-urw-nimbus-sans.conf and thought it might help. Now fc-match Helvetica shows my replacement.
    I had to restart the entire Firefox for my changes to take effect, reloading or closing/opening the tab was not sufficient

    A note about config filenames and priorities: AFAIU all ~/.config/fontconfig files are loaded via the include in the system level config file /etc/fonts/conf.d/00-user.conf. So it doesn’t matter what number you put in the filename, if you have only one user-level config file.

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.