Font De-uglification mini-HOWTO: fix ugly fonts on Linux
Ugly fonts on Linux today almost always come from one of four causes. The program falls back to a poor font. The hinting and antialiasing settings do not suit your screen. An old X11 program uses server-side bitmap fonts. Or the compositor is scaling a window. This page shows how to find which one you have and fix it.
This address used to hold the XFree86 Font De-uglification HOWTO (2001). That guide covered font paths, the xfs font server, adding TrueType fonts to XFree86 and fixing fonts in Netscape. The LDP no longer carries it. Nearly all of that is obsolete. Modern programs no longer ask the X server for fonts. They render text themselves with three libraries: fontconfig picks the font, FreeType draws the letters, and HarfBuzz shapes them. The same is true on Wayland. Installing fonts and choosing defaults is covered in the Font HOWTO. This page is about making them look right.
Step 1: find out which font you get
Many "ugly font" reports turn out to be the wrong font. A program asks for a name, fontconfig cannot find it, and it substitutes something else. Ask fontconfig what it really picks:
fc-match sans-serif
fc-match serif
fc-match monospace
fc-match "Helvetica"
Typical output is DejaVuSans.ttf: "DejaVu Sans" "Book". If a document asks for Calibri or Arial and you see a font with different widths, its line breaks and layout will be off.
Next, see the rendering settings fontconfig applies to that font:
fc-match -v sans-serif | grep -E 'antialias|hinting|hintstyle|rgba|lcdfilter|autohint'
To see every configuration file fontconfig reads, which catches a stray old ~/.fonts.conf, set the debug variable to 1024:
FC_DEBUG=1024 fc-match sans-serif | head -40
Step 2: install metric-compatible fonts
Documents and web pages often name Microsoft fonts. Free fonts with the same character widths make them lay out correctly. Fontconfig's standard 30-metric-aliases.conf already maps Arial to Liberation Sans, Calibri to Carlito and Cambria to Caladea, so you only need to install the fonts:
# Debian, Ubuntu
sudo apt install fonts-liberation fonts-crosextra-carlito fonts-crosextra-caladea fonts-noto-core
# Fedora
sudo dnf install liberation-sans-fonts liberation-serif-fonts liberation-mono-fonts \
google-carlito-fonts google-crosextra-caladea-fonts google-noto-sans-fonts
Run fc-match Calibri again. It should now say Carlito.
Step 3: match rendering to your screen
Four settings decide how sharp or smooth text looks:
- Antialiasing
- Smooths edges with grey pixels. Turn it off only for special cases, such as some bitmap fonts.
- Hinting (hintstyle)
- Nudges outlines onto the pixel grid. Values are
hintnone,hintslight,hintmediumandhintfull. Slight keeps letter shapes true by fitting only vertically. - Subpixel rendering (rgba)
- Uses the separate red, green and blue stripes of an LCD pixel for extra horizontal sharpness. It must match your panel's order:
rgb,bgr,vrgb,vbgr, ornonefor greyscale. - LCD filter
- Reduces color fringes when subpixel rendering is on:
lcddefault,lcdlight,lcdlegacy,lcdnone.
| Screen | Antialias | Hinting | Subpixel |
|---|---|---|---|
| Ordinary desktop LCD (about 96 dpi, for example a 24-inch 1920×1080) | on | slight | rgb (try it), or none |
| High-DPI laptop or 4K monitor | on | slight or none | none (greyscale) |
| Rotated monitor, OLED, or projector | on | slight | none |
| Old low-resolution screen, small text | on | full | rgb |
The OLED and rotated rows reflect the definition above: subpixel rendering assumes a fixed stripe order, and those screens do not have the usual one.
GNOME
GNOME's defaults are greyscale antialiasing and slight hinting. Change them with gsettings (no sudo; these are per user):
gsettings set org.gnome.desktop.interface font-antialiasing 'rgba' # none | grayscale | rgba
gsettings set org.gnome.desktop.interface font-rgba-order 'rgb' # rgb | bgr | vrgb | vbgr
gsettings set org.gnome.desktop.interface font-hinting 'slight' # none | slight | medium | full
gsettings set org.gnome.desktop.interface text-scaling-factor 1.1 # bigger text, 0.5 to 3.0
To undo a change, use gsettings reset org.gnome.desktop.interface font-antialiasing.
GTK 4 programs, which include most current GNOME apps, always draw text with greyscale antialiasing and never use subpixel rendering, so the rgba setting only changes GTK 3 and other programs.
KDE Plasma
Open System Settings, go to the Fonts page (under Text & Fonts in Plasma 6), and set anti-aliasing, sub-pixel rendering and hinting there. A known, confirmed bug (KDE bug 501715) is that text in some Plasma interface components does not respect the system's hinting and sub-pixel settings, so it looks blurry. If only Plasma's own panels look wrong, that is the likely cause.
Everything else (all programs)
For window managers without a settings app, or to force one setting everywhere, add a rendering rule to ~/.config/fontconfig/fonts.conf. Rendering-only edits use target="font". The Font HOWTO shows a full example. On Debian and Ubuntu, the system-wide defaults can also be chosen from a menu:
sudo dpkg-reconfigure fontconfig-config
Restart the program after any change, because most programs read font settings at start-up.
Step 4: FreeType fine-tuning
FreeType reads options from the FREETYPE_PROPERTIES environment variable. Two are worth knowing:
- Stem darkening makes thin strokes slightly bolder at small sizes, which helps light-on-dark themes and thin fonts. It is on by default for CFF (OpenType/PostScript) fonts and off by default for the autohinter. To turn it on for both:
FREETYPE_PROPERTIES="cff:no-stem-darkening=0 autofitter:no-stem-darkening=0" - TrueType interpreter version:
40is the modern engine (similar to ClearType hinting in DirectWrite).35gives the older, sharper and more pixel-snapped look, but greyscale and black-and-white only:FREETYPE_PROPERTIES="truetype:interpreter-version=35"
Try a setting on one program first, for example FREETYPE_PROPERTIES="truetype:interpreter-version=35" gedit. To compare engines side by side, use ftview from the freetype2-demos package. To make a setting permanent for your desktop session, put it in ~/.config/environment.d/fonts.conf:
FREETYPE_PROPERTIES="cff:no-stem-darkening=0 autofitter:no-stem-darkening=0"
Then log out and back in.
Step 5: old X11 programs
Programs such as xterm without options, xfontsel, or old Motif applications still use core X fonts. These come from the X server, have no antialiasing, and are the "ugly fonts" the 2001 HOWTO fought with. The xfs font server and hand-edited FontPath lines are no longer needed. Instead, tell the program to use FreeType where it can. For xterm:
xterm -fa 'DejaVu Sans Mono' -fs 11
Or make it permanent in ~/.Xresources, loaded with xrdb -merge ~/.Xresources:
XTerm*faceName: DejaVu Sans Mono
XTerm*faceSize: 11
Better still, replace such programs with a modern terminal or application. If you want classic bitmap fonts in modern programs, Debian and Ubuntu let you enable them in sudo dpkg-reconfigure fontconfig-config. Other distributions control this with the 70-*bitmaps*.conf files that fontconfig provides.
Step 6: blurry windows on Wayland
If text is blurry in only some windows at a fractional scale such as 125% or 150%, those programs are probably running as X11 clients through XWayland. The compositor then stretches their pixels. Check whether the program offers a native Wayland mode, update it, or use integer scaling (100% or 200%). This is not a font setting, and no fontconfig change will fix it.
Quick diagnosis table
| Symptom | Likely cause | Fix |
|---|---|---|
| Letters wrong shape, layout too wide or narrow | font substitution | fc-match; install metric-compatible fonts |
| Red and blue fringes | subpixel order wrong or not suited to the panel | set rgba to the right order, or none |
| Fuzzy at small sizes | no hinting on a low-DPI screen | hintslight or hintfull |
| Thin, faint text | no stem darkening | FREETYPE_PROPERTIES stem darkening |
| Jagged, no smoothing, one program only | core X fonts | use -fa/faceName, or a modern program |
| Blurry in some windows only, fractional scale | XWayland scaling | native Wayland mode or integer scale |
| Settings ignored | old ~/.fonts.conf overriding, or program not restarted | FC_DEBUG=1024, move the old file to ~/.config/fontconfig/ |
Sources
- fonts-conf: Fontconfig user and configuration reference (2.15), freedesktop.org
- 30-metric-aliases.conf, fontconfig source
- FreeType driver properties (FREETYPE_PROPERTIES, stem darkening, interpreter-version) and FreeType home page
- org.gnome.desktop.interface schema (font-antialiasing, font-hinting, font-rgba-order), GNOME
- On fractional scales, fonts and hinting (GTK 4 uses greyscale antialiasing only), GTK blog
- Fonts, KDE System Settings documentation and KDE bug 501715
- Fonts, Debian Wiki (dpkg-reconfigure fontconfig-config, ftview) and fontconfig-config file list, Debian 13
- xterm(1) (-fa, -fs, faceName), Debian
- environment.d(5), man7.org