How To Set Default Fonts and Font Aliases on Linux

Font Woes

It’s fairly straightforward to set the default font used in native apps on a modern Linux desktop, or the default fonts used to render web pages in your browser of choice.

But if you’re reading this, you probably know that that’s far from the end of the story. You might have noticed that Firefox and Chrome rudely ignore your font settings for many websites. This is because many (if not most) popular sites, including Google, Yahoo, Facebook or GitHub, specify preferred fonts for text:

Site Font Specification

Google

arial, sans-serif

Yahoo

Helvetica Neue, Helvetica, Arial

Facebook

lucida grande, tahoma, verdana, arial, sans-serif

GitHub

Helvetica, arial, freesans, clean, sans-serif

(Retrieved on 02/21/2014)

You might immediately notice that the most commonly used fonts on these sites, Arial and Helvetica, are fonts that come bundled with Microsoft Windows, and are most likely not installed on your Linux system. In this case, what font is actually used is anyone’s guess. If they are installed (e.g., via a package like ttf-ms-fonts or directly copied from a Windows machine), well, you still probably want to display your favorite font instead :)

So, let’s find out what your default fonts and aliases are with fc-match:

for family in serif sans-serif monospace Arial Helvetica Verdana "Times New Roman" "Courier New"; do
  echo -n "$family: "
  fc-match "$family"
done

This is what I get on my machine by default:

serif: DejaVuSerif.ttf: "DejaVu Serif" "Book"
sans-serif: DejaVuSans.ttf: "DejaVu Sans" "Book"
monospace: DejaVuSansMono.ttf: "DejaVu Sans Mono" "Book"
Arial: DejaVuSans.ttf: "DejaVu Sans" "Book"
Helvetica: n019003l.pfb: "Nimbus Sans L" "Regular"
Verdana: DejaVuSans.ttf: "DejaVu Sans" "Book"
Times New Roman: DejaVuSerif.ttf: "DejaVu Serif" "Book"
Courier New: DejaVuSansMono.ttf: "DejaVu Sans Mono" "Book"

Font Configuration Files

So, assuming you’ve installed your fonts of choice (via a package, copying to /usr/share/fonts or ~/.fonts - please verify with the fc-list command), how do you set them as default in all apps and web sites?

Well, there are two places where fonts are configured: system-wide configuration resides in /etc/fonts/, and per-user configs are stored in ~/.config/fontconfig/fonts.conf (note that this used to be ~/.fonts.conf before fontconfig 2.10.1). For simplicity’s sake, we’ll do it in ~/.config/fontconfig/fonts.conf.

Let’s open up ~/.config/fontconfig/fonts.conf, or create it if it doesn’t already exist. Put the following skeleton structure in there:

<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
</fontconfig>

We will put all of our custom configuration between <fontconfig> and </fontconfig>.

Setting Default Fonts

First, let’s set the default serif, sans serif, and monospace fonts. I’ll use the beautiful Chrome OS fonts as an example (ttf-chromeos-fonts if you’re running Arch Linux). Insert the following between <fontconfig> and </fontconfig>:

  <!-- Set preferred serif, sans serif, and monospace fonts. -->
  <alias>
    <family>serif</family>
    <prefer><family>Tinos</family></prefer>
  </alias>
  <alias>
    <family>sans-serif</family>
    <prefer><family>Arimo</family></prefer>
  </alias>
  <alias>
    <family>sans</family>
    <prefer><family>Arimo</family></prefer>
  </alias>
  <alias>
    <family>monospace</family>
    <prefer><family>Cousine</family></prefer>
  </alias>

Aliasing Microsoft Fonts

Now, we will create aliases for commonly used fonts like Arial and Helvetica, so that our favorite fonts will always be used instead of these fonts, e.g. when requested by a web site.

Insert the following between <fontconfig> and </fontconfig>, after the previous snippet:

  <!-- Aliases for commonly used MS fonts. -->
  <match>
    <test name="family"><string>Arial</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Arimo</string>
    </edit>
  </match>
  <match>
    <test name="family"><string>Helvetica</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Arimo</string>
    </edit>
  </match>
  <match>
    <test name="family"><string>Verdana</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Arimo</string>
    </edit>
  </match>
  <match>
    <test name="family"><string>Tahoma</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Arimo</string>
    </edit>
  </match>
  <match>
    <!-- Insert joke here -->
    <test name="family"><string>Comic Sans MS</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Arimo</string>
    </edit>
  </match>
  <match>
    <test name="family"><string>Times New Roman</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Tinos</string>
    </edit>
  </match>
  <match>
    <test name="family"><string>Times</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Tinos</string>
    </edit>
  </match>
  <match>
    <test name="family"><string>Courier New</string></test>
    <edit name="family" mode="assign" binding="strong">
      <string>Cousine</string>
    </edit>
  </match>

Note that the Microsoft fonts are aliased directly to the our preferred substitute fonts. Aliasing to generic families (serif, sans-serif etc.) may or may not work depending on your configuration in /etc/fonts (they didn’t work for me), so it’s safer this way.

This list is of course by no means definitive; add/remove aliases as you like.

The Result

You’ll need to log out and back in for all applications to update. You should see the difference immediately:

Google search results, before (Arial):

/assets/files/font_config_before.png

Google search results, after (Arimo):

/assets/files/font_config_after.png

You can verify that the aliases have been set up correctly with fc-match:

for family in serif sans-serif monospace Arial Helvetica Verdana "Times New Roman" "Courier New"; do
  echo -n "$family: "
  fc-match "$family"
done

which should now give you something like:

serif: Tinos-Regular.ttf: "Tinos" "Regular"
sans-serif: Arimo-Regular.ttf: "Arimo" "Regular"
monospace: Cousine-Regular.ttf: "Cousine" "Regular"
Arial: Arimo-Regular.ttf: "Arimo" "Regular"
Helvetica: Arimo-Regular.ttf: "Arimo" "Regular"
Verdana: Arimo-Regular.ttf: "Arimo" "Regular"
Times New Roman: Tinos-Regular.ttf: "Tinos" "Regular"
Courier New: Cousine-Regular.ttf: "Cousine" "Regular"

Other Notes

Some existing examples you may find online show the following syntax:

<!-- Deprecated syntax -->
<match target="pattern" name="family">
  <test name="family" qual="any"><string>Arial</string></test>
  ...
</match>

This will produce an error message like

Fontconfig error: "/home/username/.config/fontconfig/fonts.conf", line 38: invalid attribute 'name'

The fix is to change <match target="pattern" name="family"> to just <match>, as shown above.

About the author

I am a software engineer by profession and a passionate technology geek in my free time.