All Articles

Variable Fonts Explained: One Font File That Does Everything

Variable fonts are the biggest innovation in type technology in decades. A single font file can replace dozens of individual weight and style variants — and it's revolutionising how designers and developers work with typography.

The Old Way

Traditional font families ship as multiple individual files: Roboto-Thin.ttf, Roboto-Light.ttf, Roboto-Regular.ttf, Roboto-Medium.ttf, Roboto-Bold.ttf, Roboto-Black.ttf — plus italic variants of each. To use a complete family, you might load 12 separate files, totalling several hundred kilobytes.

The Variable Font Way

A variable font stores the design at "master" positions (typically the extremes of each axis) and uses mathematical interpolation to generate any intermediate value. One file, infinite weights.

Roboto as a variable font: one file, all weights, all widths. At ~180KB instead of ~400KB for the full static family. And with CSS, you can access any value: font-weight: 347 — a weight that doesn't exist in the static family.

Variation Axes

Variable fonts can vary along multiple axes simultaneously:

  • Weight (wght) — from hairline to ultra-black
  • Width (wdth) — from condensed to expanded
  • Slant (slnt) — from upright to oblique
  • Italic (ital) — toggle between roman and italic
  • Optical Size (opsz) — adjust details based on display size
  • Custom axes — typeface-specific (e.g., "Casual" in Recursive)

Best Variable Fonts Available Free

  • Inter — Variable weight, the designer's Swiss Army knife
  • Bricolage Grotesque — Variable weight + width for display use
  • Recursive — Five axes including a "Casual" personality axis
  • Fraunces — Optical size variable serif with stunning detail at large sizes
  • Raleway — Variable weight from ultra-thin to ultra-bold

Using Variable Fonts in CSS

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap');

h1 { font-family: 'Inter', sans-serif; font-weight: 800; }
p  { font-family: 'Inter', sans-serif; font-weight: 400; }

The 100..900 range syntax loads the full variable font with all weights accessible. One HTTP request. One cached file.