Variable Font Technology
Variable fonts — a single font file containing a continuous range of styles (weight, width, slant, optical size) controlled by design axes, replacing entire font families.
You are a file format specialist with deep expertise in variable font technology, including OpenType 1.8+ fvar/gvar/STAT tables, design axis configuration, CSS font-variation-settings and high-level properties, fontmake build workflows, instance generation with varLib.instancer, and web font optimization with subsetting. ## Key Points - **Extensions:** `.ttf`, `.otf`, `.woff2` (same as static fonts, format is backward-compatible) - **MIME types:** Same as regular fonts - **Specification:** OpenType 1.8+ (ISO/IEC 14496-22:2019) - **Outline types:** TrueType (gvar) or CFF2 (both support variation) - **CSS syntax:** `font-variation-settings` or high-level properties - Named instances = predefined axis positions (e.g., "Bold" = wght:700) - Applications can list these as traditional style options - Light master (wght=300) - Regular master (wght=400, default) - Bold master (wght=700) - **Web typography:** Single WOFF2 replacing 4-12 static font files - **Responsive design:** Adjust weight/width based on viewport or container
skilldb get file-formats-skills/Variable Font TechnologyFull skill: 378 linesYou are a file format specialist with deep expertise in variable font technology, including OpenType 1.8+ fvar/gvar/STAT tables, design axis configuration, CSS font-variation-settings and high-level properties, fontmake build workflows, instance generation with varLib.instancer, and web font optimization with subsetting.
Variable Font Technology
Overview
Variable fonts are an extension of the OpenType specification (version 1.8, released 2016) that allows a single font file to contain a continuous range of design variations along defined axes. Instead of shipping separate files for Regular, Bold, Light, Condensed, and Italic, a variable font encodes the entire design space in one file with interpolation between master designs.
Developed jointly by Apple, Google, Microsoft, and Adobe, variable fonts dramatically reduce the number of font files needed for web typography while enabling fine-grained typographic control that was previously impossible without custom font files for each weight or width.
Core Philosophy
Variable fonts represent a fundamental shift in typography: instead of shipping separate font files for each weight, width, italic angle, and optical size, a single variable font file contains a continuous design space that can be interpolated to any point along its defined axes. One file replaces what previously required a dozen or more static font files.
The practical benefits are significant: smaller total file sizes (one variable font typically replaces 6-12 static fonts with less total data), the ability to use precise intermediate weights (not just Regular and Bold, but weight 450 or 650), responsive typography that adapts weight and width to viewport size, and smoother animation between typographic states. For web projects, variable fonts reduce HTTP requests and total font download size simultaneously.
Variable fonts use the same OpenType container (.ttf or .otf) and are deployed on the web as WOFF2. Browser support is now universal across modern browsers. Use CSS font-variation-settings or the higher-level font-weight, font-stretch, and font-style properties to control variation axes. When selecting a variable font, evaluate which axes it exposes (weight, width, slant, optical size, and potentially custom axes) to ensure it covers your design needs.
Technical Specifications
- Extensions:
.ttf,.otf,.woff2(same as static fonts, format is backward-compatible) - MIME types: Same as regular fonts
- Specification: OpenType 1.8+ (ISO/IEC 14496-22:2019)
- Outline types: TrueType (gvar) or CFF2 (both support variation)
- CSS syntax:
font-variation-settingsor high-level properties
Registered Design Axes
| Tag | Axis | CSS Property | Range |
|---|---|---|---|
wght | Weight | font-weight | 1-1000 (typically 100-900) |
wdth | Width | font-stretch | >0% (typically 75-125%) |
ital | Italic | font-style: italic | 0-1 (binary toggle) |
slnt | Slant | font-style: oblique Xdeg | -90 to 90 degrees |
opsz | Optical size | font-optical-sizing | Typically 8-144 pt |
Custom axes use uppercase tags (e.g., GRAD for Grade, CASL for Casual).
Key OpenType Tables
[Variation Tables]
fvar — Font Variations: defines axes (tag, min, default, max, name)
gvar — Glyph Variations: per-glyph deltas for TrueType outlines
CFF2 — Charstring variations for PostScript outlines
cvar — CVT Variations: hinting value adjustments
HVAR — Horizontal Metrics Variations
VVAR — Vertical Metrics Variations
MVAR — Metrics Variations (global metrics like ascender, descender)
STAT — Style Attributes: axis value names for UI presentation
avar — Axis Variations: non-linear axis mapping (piecewise linear)
[Instance Records in fvar]
- Named instances = predefined axis positions (e.g., "Bold" = wght:700)
- Applications can list these as traditional style options
How Variation Works
Master designs are placed at specific points in the design space:
- Light master (wght=300)
- Regular master (wght=400, default)
- Bold master (wght=700)
For any requested weight value, the renderer interpolates:
wght=550 → blend 50% between Regular(400) and Bold(700)
Each glyph stores deltas (point offsets) from the default master.
The renderer applies: final_point = default_point + Σ(delta_i × scalar_i)
where scalar_i depends on axis position and region influence.
How to Work With It
Using in CSS
/* Basic usage with font-variation-settings */
@font-face {
font-family: 'Inter';
src: url('Inter-Variable.woff2') format('woff2');
font-weight: 100 900;
font-display: swap;
}
/* Using standard CSS properties (preferred) */
h1 {
font-family: 'Inter', sans-serif;
font-weight: 750; /* any value, not just 400/700 */
font-stretch: 87.5%; /* if width axis exists */
font-style: oblique 12deg; /* if slant axis exists */
font-optical-sizing: auto; /* if opsz axis exists */
}
/* Using font-variation-settings for custom axes */
.text {
font-variation-settings:
"wght" 625,
"wdth" 90,
"GRAD" -50, /* custom Grade axis */
"CASL" 0.5; /* custom Casual axis */
}
/* Animation (smooth transitions between any values) */
.heading {
font-weight: 400;
transition: font-weight 0.3s ease;
}
.heading:hover {
font-weight: 800;
}
/* Keyframe animation */
@keyframes breathe {
0%, 100% { font-variation-settings: "wght" 300; }
50% { font-variation-settings: "wght" 700; }
}
Inspecting Variable Fonts
# Python with fonttools
from fontTools.ttLib import TTFont
font = TTFont('variable.ttf')
if 'fvar' in font:
fvar = font['fvar']
print("Axes:")
for axis in fvar.axes:
print(f" {axis.axisTag}: {axis.minValue} - {axis.maxValue} (default: {axis.defaultValue})")
print("\nNamed instances:")
for instance in fvar.instances:
name = font['name'].getDebugName(instance.subfamilyNameID)
print(f" {name}: {instance.coordinates}")
# Command line
fonttools varLib.instancer --help # instance generation tool
# Web inspection
# https://wakamaifondue.com — drag-and-drop variable font inspector
# https://v-fonts.com — variable font playground
Creating Variable Fonts
# From multiple UFO sources with fontmake
# pip install fontmake
fontmake -m MyFont.designspace -o variable-ttf
fontmake -m MyFont.designspace -o variable-cff2
# The .designspace file defines sources and axes:
<!-- MyFont.designspace -->
<?xml version="1.0" encoding="UTF-8"?>
<designspace format="4.1">
<axes>
<axis tag="wght" name="Weight" minimum="300" default="400" maximum="800"/>
</axes>
<sources>
<source filename="MyFont-Light.ufo" familyname="MyFont" stylename="Light">
<location><dimension name="Weight" xvalue="300"/></location>
</source>
<source filename="MyFont-Regular.ufo" familyname="MyFont" stylename="Regular">
<location><dimension name="Weight" xvalue="400"/></location>
</source>
<source filename="MyFont-Bold.ufo" familyname="MyFont" stylename="Bold">
<location><dimension name="Weight" xvalue="800"/></location>
</source>
</sources>
</designspace>
Generating Static Instances from Variable Font
# Extract specific instances
fonttools varLib.instancer variable.ttf wght=700 -o Bold.ttf
fonttools varLib.instancer variable.ttf wght=400 wdth=75 -o CondensedRegular.ttf
# Generate all named instances
fonttools varLib.instancer variable.ttf --named-instances --output-dir=./instances/
Subsetting for Web
# Subset variable font (preserving variation data)
pyftsubset variable.ttf \
--output-file=variable-latin.woff2 \
--flavor=woff2 \
--unicodes="U+0000-00FF" \
--layout-features="kern,liga,calt" \
--variations="wght:300:800" # preserve weight range
Common Use Cases
- Web typography: Single WOFF2 replacing 4-12 static font files
- Responsive design: Adjust weight/width based on viewport or container
- Dark mode: Slightly increase weight for light-on-dark text (optical compensation)
- Animated typography: Smooth transitions between styles on hover/scroll
- Accessibility: Users can fine-tune weight and width for readability
- App UI: One font file for all UI contexts (navigation, body, headings)
- Branding: Continuous design space for nuanced typographic expression
Pros & Cons
Pros
- Single file replaces entire font family (4-20+ files)
- Smaller total download size for websites using multiple weights
- Continuous design space — any value on any axis, not just predefined styles
- CSS animation between axis values is smooth and hardware-accelerated
- Optical size axis automatically adjusts design for different point sizes
- Named instances provide familiar style names for applications
- Backward compatible — static font applications see default instance
Cons
- Single file is larger than any individual static font (30-50% larger than one weight)
- If only using 1-2 weights, static fonts may be smaller total download
- Browser/OS support for custom axes varies
- Some applications show all named instances but not custom axis sliders
font-variation-settingsis lower-level than high-level CSS properties- CFF2 variable fonts have less tool support than TrueType variable fonts
- Creating variable fonts requires more design effort (masters must be compatible)
Compatibility
| Platform | Support | Notes |
|---|---|---|
| Chrome | 66+ | Full support including animations |
| Firefox | 62+ | Full support |
| Safari | 11+ | Full support (macOS and iOS) |
| Edge | 17+ | Full support |
| Android | 8.0+ | System and web |
| macOS | 10.13+ | System-wide support |
| Windows | 10 1709+ | DirectWrite support |
| Adobe apps | CC 2018+ | Full support in InDesign, Illustrator, Photoshop |
Notable variable fonts: Inter, Recursive, Roboto Flex, Source Sans 3, IBM Plex, Fraunces, Commissioner, Plus Jakarta Sans.
Tools: Wakamaifondue (web inspector), Samsa (web testing), Axis-Praxis (playground), Glyphs/FontLab/RoboFont (creation).
Practical Usage
Optimize a variable font for web delivery with subsetting
# Install fonttools with woff2 support
pip install fonttools brotli
# Subset to Latin characters only, preserving weight axis
pyftsubset InterVariable.ttf \
--output-file=Inter-Latin.woff2 \
--flavor=woff2 \
--unicodes="U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD" \
--layout-features="kern,liga,calt,cv01,cv02" \
--variations="wght:300:800"
# Generate a static instance from a variable font
fonttools varLib.instancer InterVariable.ttf wght=700 -o Inter-Bold.ttf
# Generate all named instances
fonttools varLib.instancer InterVariable.ttf \
--named-instances --output-dir=./static-instances/
echo "Variable: $(stat -c%s InterVariable.ttf) bytes"
echo "Subset WOFF2: $(stat -c%s Inter-Latin.woff2) bytes"
Implement responsive typography with CSS variable fonts
/* Load variable font with full weight range */
@font-face {
font-family: 'Inter';
src: url('Inter-Latin.woff2') format('woff2');
font-weight: 100 900;
font-display: swap;
}
/* Responsive weight adjustment based on viewport */
body {
font-family: 'Inter', system-ui, sans-serif;
font-weight: 400;
font-optical-sizing: auto;
}
/* Slightly heavier text for dark mode (optical compensation) */
@media (prefers-color-scheme: dark) {
body { font-weight: 350; }
h1 { font-weight: 650; }
}
/* Fluid weight scaling with container queries */
@container (min-width: 600px) {
.card-title {
font-weight: 600;
font-stretch: 110%;
}
}
/* Smooth weight animation on interaction */
.nav-link {
font-weight: 400;
transition: font-weight 0.2s ease, font-stretch 0.2s ease;
}
.nav-link:hover {
font-weight: 700;
}
Inspect variable font axes and instances with Python
from fontTools.ttLib import TTFont
font = TTFont('MyVariable.ttf')
# Check if font is variable
if 'fvar' not in font:
print("Not a variable font")
exit()
fvar = font['fvar']
name_table = font['name']
print("=== Design Axes ===")
for axis in fvar.axes:
axis_name = name_table.getDebugName(axis.axisNameID)
print(f" {axis.axisTag} ({axis_name}): {axis.minValue} - {axis.maxValue} "
f"(default: {axis.defaultValue})")
print("\n=== Named Instances ===")
for inst in fvar.instances:
inst_name = name_table.getDebugName(inst.subfamilyNameID)
coords = ", ".join(f"{k}={v}" for k, v in inst.coordinates.items())
print(f" {inst_name}: {coords}")
# Check for STAT table (axis value names)
if 'STAT' in font:
print("\n=== STAT Axis Values ===")
for val in font['STAT'].table.AxisValueArray.AxisValue:
print(f" {name_table.getDebugName(val.ValueNameID)}")
Anti-Patterns
Using font-variation-settings instead of high-level CSS properties for registered axes. Setting font-variation-settings: "wght" 700 instead of font-weight: 700 bypasses the CSS cascade for font properties, causes inheritance issues, and does not work with font-style: oblique Xdeg or font-optical-sizing: auto. Always use standard CSS properties for registered axes (wght, wdth, ital, slnt, opsz) and reserve font-variation-settings only for custom axes.
Loading a full variable font when only one or two weights are needed. A variable font file is 30-50% larger than a single static weight. If a site only uses Regular (400) and Bold (700), two static WOFF2 files will be smaller than the variable font. Evaluate your actual usage: variable fonts save bandwidth only when using 3+ weights or widths from the same family.
Animating font-variation-settings without considering performance. While CSS transitions on variable font axes are visually smooth, animating font-variation-settings triggers layout recalculation on every frame because text reflows. Limit animations to non-layout contexts (hover effects on short text, decorative headings) and avoid animating body text or long paragraphs.
Forgetting to configure the STAT table, causing incorrect style names in application menus. Without a properly configured STAT (Style Attributes) table, applications like Word, InDesign, and system font pickers will display confusing or duplicate style names. Always populate STAT with axis value entries that map to familiar names (Regular, Bold, Condensed, etc.).
Subsetting a variable font and accidentally removing axis data. Running pyftsubset without the --variations flag strips variation tables, producing a static font at the default instance. Always include --variations="wght:MIN:MAX" (or * to keep all axes) when subsetting variable fonts for web delivery.
Related Formats
- TTF/OTF — Static font formats that variable fonts extend
- WOFF2 — Compressed delivery format (variable fonts served as WOFF2)
- GX Variations — Apple's earlier variation technology (precursor)
- Multiple Master — Adobe's legacy variation format (Type 1, deprecated)
- COLR v1 — Color font format that can also be variable
- designspace — Source format defining variable font axes and masters
Install this skill directly: skilldb add file-formats-skills
Related Skills
3MF 3D Manufacturing Format
The 3MF file format — the modern replacement for STL in 3D printing, supporting colors, materials, multi-object assemblies, and precise manufacturing data in a single package.
7-Zip Compressed Archive
The 7z archive format — open-source high-ratio compression using LZMA2, with strong AES-256 encryption, solid archives, and multi-threading support.
AAC (Advanced Audio Coding)
A lossy audio codec standardized as part of MPEG-2 and MPEG-4, designed to supersede MP3 with better quality at equivalent or lower bitrates.
AC3 (Dolby Digital)
Dolby's surround sound audio codec used in cinema, DVD, Blu-ray, and broadcast television for multichannel 5.1 audio delivery.
AI Adobe Illustrator Format
AI is Adobe Illustrator's native vector graphics file format, used for
AIFF (Audio Interchange File Format)
Apple's uncompressed audio format storing raw PCM data, serving as the Mac equivalent of WAV for professional audio production.