Font Converter

How to Reduce Font File Size: Complete Optimization Guide

Comprehensive guide to reducing font file sizes through compression, subsetting, and format optimization. Improve page load times and performance without sacrificing quality.

TL;DR

In Simple Terms

Three main techniques: Convert to WOFF2 (60-70% smaller), subset to Latin characters (50-80% smaller), and limit font weights (2-3 instead of 6+).Target: Under 100KB total for all fonts. A typical optimized setup is 14-28KB per weight in WOFF2 format with Latin subset.Tools: Glyphhanger (auto-scans your site), pyftsubset (CLI), or Font Squirrel (web GUI). Always keep original fonts as backup.

Share this page to:

Large font files significantly impact website performance, slowing down page loads and consuming bandwidth. A typical web font family with multiple weights and styles can easily exceed 500KB-1MB, creating a noticeable delay in text rendering and overall user experience. For users on slower connections or mobile devices, this delay becomes even more pronounced, potentially leading to higher bounce rates and reduced engagement.

Font optimization is one of the most effective performance improvements you can make. By reducing font file sizes through compression, subsetting, and format optimization, you can achieve 70-95% size reductions while maintaining full visual quality for your specific use case. A well-optimized font implementation typically uses 20-50KB per weight instead of 200-500KB, dramatically improving load times without any visible degradation.

This guide covers everything from analyzing your current font files to implementing aggressive optimization strategies. You'll learn practical techniques for font subsetting (removing unused characters), format conversion to modern compressed formats, advanced compression methods, and how to measure the impact of your optimizations. Whether you're dealing with Google Fonts, custom typefaces, or icon fonts, these techniques will help you achieve optimal performance.

Understanding Font File Size

What Makes Font Files Large?

1. Character Coverage

  • Full Unicode fonts: 50,000+ characters (Chinese, Japanese, Korean)
  • Latin Extended: 1,000-2,000 characters (accents, special symbols)
  • Basic Latin only: 100-200 characters (A-Z, a-z, 0-9, punctuation)
  • • Each character adds data: glyph outline, metrics, kerning pairs
  • • Most websites use only 200-400 unique characters

2. Font Features and Hinting

  • OpenType features: Ligatures, alternates, stylistic sets
  • TrueType hinting: Instructions for pixel-perfect rendering at small sizes
  • Kerning tables: Spacing adjustments between character pairs
  • Metadata: Font names, licensing, versioning information
  • Feature-rich fonts can be 2-3× larger than minimal versions

3. File Format Efficiency

  • TTF/OTF: Uncompressed, largest file sizes (100-500KB per weight)
  • WOFF: ZIP compression applied to TTF/OTF (40-60% smaller)
  • WOFF2: Brotli compression + optimized tables (50-70% smaller than WOFF)
  • EOT: Legacy IE format, usually larger than WOFF
  • Modern WOFF2 is typically 20-30KB for basic Latin subset

4. Multiple Weights and Styles

  • • Each weight (Light, Regular, Medium, Bold, Black) is a separate file
  • • Each style (Normal, Italic) doubles the number of files
  • • Complete family: 8-16 files totaling 1-4MB unoptimized
  • • Variable fonts can replace multiple weights in single file

Typical Font File Sizes

Full Latin Extended (TTF/OTF):200-500KB
Full Latin Extended (WOFF2):80-200KB
Basic Latin subset (WOFF2):15-30KB
Icon fonts (100-200 icons, WOFF2):10-20KB
Variable font (full range, WOFF2):30-80KB

Why Font Size Matters

Performance Impact

Page Load Time: 500KB of fonts adds 1-3 seconds on 3G connections

Render Blocking: Fonts block text rendering until loaded (FOIT)

Bandwidth Cost: Large fonts consume mobile data allowances

Cache Size: Bloated cache reduces effectiveness of browser caching

Core Web Vitals: Large fonts negatively impact LCP and CLS metrics

User Experience Impact

Perceived Performance: Users notice delays over 100ms

Mobile Users: 60% of traffic on mobile sees amplified font loading delays

Bounce Rate: 53% of users abandon sites that take 3+ seconds to load

Accessibility: Slow loads particularly impact users with disabilities

Business Impact

SEO Rankings: Page speed is a Google ranking factor

Conversion Rates: 1 second delay = 7% reduction in conversions

CDN Costs: Bandwidth charges multiply with large font files

Mobile Performance: Better scores in mobile-first indexing

Analyzing Font Files

Step 1: Check Current Font Sizes

Browser DevTools Network Tab:

  1. Open DevTools (F12)
  2. Go to Network tab
  3. Filter by "Font"
  4. Refresh page (Ctrl+R)
  5. Note file names and sizes
  6. Check "Size" vs "Transferred" columns

Step 2: Analyze Character Usage

Command Line Analysis (fonttools):

# Install fonttools
pip install fonttools brotli

# Get glyph count
ttx -l font.ttf | grep "glyf" -A 1

# List all characters
ttx -t cmap font.ttf

# Get detailed font info
ttx -o font.ttx font.ttf

Online Tools:

  • FontDrop! (fontdrop.info) - Drag & drop font analysis
  • Wakamaifondue (wakamaifondue.com) - Detailed font feature inspection
  • FontSquirrel Webfont Generator - Shows glyph count and size estimates

Step 3: Identify Actual Character Usage

Analyze your website content to determine which characters you actually use:

// JavaScript to extract unique characters
const uniqueChars = new Set(
  document.body.innerText.split('')
);
console.log('Unique characters:', uniqueChars.size);
console.log('Characters:', Array.from(uniqueChars).sort().join(''));

// Copy to clipboard
navigator.clipboard.writeText(
  Array.from(uniqueChars).sort().join('')
);

Run this in browser console to see exactly which characters your site uses

Compression Methods

Method 1: Convert to WOFF2 (Highest Priority)

Impact: 50-70% size reduction vs TTF/OTF, 30-40% vs WOFF

Using fonttools (Recommended):

# Install fonttools with WOFF2 support
pip install fonttools brotli

# Convert single file
ttx -f -o output.woff2 input.ttf

# OR use woff2_compress directly
woff2_compress input.ttf

# Batch convert all TTF files
for file in *.ttf; do
  ttx -f -o "${file%.ttf}.woff2" "$file"
done

Using Online Tools:

  • CloudConvert: Batch conversion, preserves metadata
  • font-converter.net: Simple drag-and-drop interface
  • Online Font Converter: Multiple format output

Method 2: Strip Unnecessary Data

Impact: 5-15% additional size reduction

# Remove hinting (if not needed)
pyftsubset font.ttf \
  --drop-tables+=DSIG,GDEF,GPOS,GSUB,hdmx,kern,LTSH,prep,VDMX \
  --output-file=font-no-hinting.ttf

# Remove OpenType features
pyftsubset font.ttf \
  --layout-features- \
  --output-file=font-no-features.ttf

# Remove name table bloat
pyftsubset font.ttf \
  --name-IDs='*' \
  --name-legacy \
  --name-languages='*' \
  --output-file=font-minimal.ttf

Method 3: Use Variable Fonts

Impact: One variable font file replaces 4-8 static weight files

Before: Regular (100KB) + Medium (105KB) + Bold (110KB) + Black (115KB) = 430KB

After: Variable font with weight axis (100-900) = 120KB

/* CSS usage */
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont-variable.woff2') format('woff2-variations');
  font-weight: 100 900; /* Full range */
}

/* Use any weight value */
h1 { font-weight: 350; }
h2 { font-weight: 650; }

Font Subsetting Techniques

Technique 1: Basic Latin Subsetting

Impact: 70-90% size reduction for English-only sites

# Basic Latin (A-Z, a-z, 0-9, punctuation)
pyftsubset font.ttf \
  --output-file=font-basic-latin.woff2 \
  --flavor=woff2 \
  --unicodes="U+0020-007F"

# Result: 200KB → 20KB (90% reduction)

Technique 2: Latin Extended Subsetting

Impact: 60-80% size reduction, supports European languages

# Latin Extended (includes accents: é, ñ, ü, etc.)
pyftsubset font.ttf \
  --output-file=font-latin-ext.woff2 \
  --flavor=woff2 \
  --unicodes="U+0020-007F,U+00A0-00FF,U+0100-017F"

# Result: 200KB → 40KB (80% reduction)

Technique 3: Custom Character Set

Impact: Maximum optimization for specific content

Create text file with your characters:

# Save your actual content to chars.txt
echo "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .,!?" > chars.txt

# Subset using text file
pyftsubset font.ttf \
  --output-file=font-custom.woff2 \
  --flavor=woff2 \
  --text-file=chars.txt

Advanced: Multiple Subsets with unicode-range:

/* Create multiple subsets for progressive loading */

/* Latin subset */
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont-latin.woff2') format('woff2');
  unicode-range: U+0020-007F;
}

/* Latin Extended subset */
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-017F;
}

/* Only loads when characters in range are used */

Technique 4: Automated Subsetting with Google Fonts

Impact: Google automatically subsets and serves optimal files

<!-- Only loads Latin subset automatically -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">

<!-- Specify subset explicitly -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&subset=latin&display=swap" rel="stylesheet">

<!-- Multiple subsets -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&subset=latin,latin-ext&display=swap" rel="stylesheet">

Format Optimization

FormatCompressionBrowser SupportRecommended Use
WOFF2

Best (Brotli)

50-70% smaller than TTF

97% of browsers

All modern browsers

✓ Primary format
✓ Use for all modern sites
WOFF

Good (ZIP)

40-60% smaller than TTF

99% of browsers

IE9+, all modern browsers

✓ Fallback for IE11
✓ Legacy browser support
TTF/OTF

None

Baseline size

Universal

All browsers, desktop apps

✗ Avoid for web
✓ Source files only
EOT

Poor

Similar to TTF

IE6-8 only

Legacy format

✗ Obsolete
Only if supporting IE8

Optimal Format Strategy

/* Modern approach (WOFF2 only) */
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont.woff2') format('woff2');
  font-display: swap;
}

/* With IE11 fallback */
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont.woff2') format('woff2'),
       url('/fonts/myfont.woff') format('woff');
  font-display: swap;
}

Best practice: WOFF2 primary, WOFF fallback only if supporting IE11

Advanced Optimization Techniques

Technique 1: Font Loading Strategies

Preload Critical Fonts:

<!-- Preload main font for instant rendering -->
<link rel="preload" 
      href="/fonts/main-font.woff2" 
      as="font" 
      type="font/woff2" 
      crossorigin>

<!-- Load other weights later -->
<link rel="preload" 
      href="/fonts/bold-font.woff2" 
      as="font" 
      type="font/woff2" 
      crossorigin 
      media="(max-width: 768px)">

Use font-display Effectively:

@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont.woff2') format('woff2');
  
  /* Options:
     swap - Show fallback immediately, swap when loaded
     optional - Only use if loads fast (<100ms)
     fallback - Brief invisible period, then swap
     block - Wait for font (default, slow) */
  
  font-display: swap; /* Recommended for most cases */
}

Technique 2: Dynamic Subsetting

Load only the characters you need based on page content

/* Split font into multiple unicode-range subsets */

/* Numbers only (small) */
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont-numbers.woff2') format('woff2');
  unicode-range: U+0030-0039;
}

/* Common letters (medium) */
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont-common.woff2') format('woff2');
  unicode-range: U+0041-005A, U+0061-007A;
}

/* Special characters (loads only if needed) */
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont-special.woff2') format('woff2');
  unicode-range: U+00A0-00FF;
}

/* Browser automatically loads only required subsets */

Technique 3: Self-Host Google Fonts

Download and optimize Google Fonts for better control and performance

Using google-webfonts-helper:

  1. Visit google-webfonts-helper.herokuapp.com
  2. Search for your font (e.g., "Roboto")
  3. Select charsets (Latin, Latin Extended)
  4. Select styles (Regular 400, Bold 700)
  5. Download optimized WOFF2 files
  6. Copy generated CSS

Benefits: No external requests, better compression, full control over subset

Technique 4: Icon Font Optimization

Reduce icon font sizes by removing unused icons

# Subset FontAwesome to only used icons
pyftsubset fontawesome.ttf \
  --output-file=fontawesome-minimal.woff2 \
  --flavor=woff2 \
  --unicodes="U+f015,U+f007,U+f0e0,U+f002" # home, user, envelope, search

# Result: 150KB → 8KB (95% reduction)

# Alternative: Use IcoMoon or Fontello to build custom icon fonts
# with only the icons you need

Implementation Strategy

Step-by-Step Implementation

  1. Audit Current Fonts
    • Measure total font file sizes
    • Identify all weights and styles in use
    • Check actual character usage on site
    • Note current page load times
  2. Prioritize Optimizations
    • Convert to WOFF2 (quick win, 50% reduction)
    • Subset to Latin Extended (another 60-80%)
    • Remove unused weights
    • Consider variable fonts for multiple weights
  3. Implement Changes
    • Create optimized font files
    • Update @font-face declarations
    • Add font-display: swap
    • Implement preload for critical fonts
  4. Test Thoroughly
    • Check all characters render correctly
    • Verify fonts load in all target browsers
    • Test on slow connections (throttle network)
    • Validate no missing glyphs
  5. Measure Impact
    • Compare before/after file sizes
    • Measure page load improvement
    • Check Core Web Vitals (LCP, CLS)
    • Monitor real user metrics

Complete Example: Before & After

❌ Before Optimization (1.2MB total):

@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont-light.ttf');
  font-weight: 300;
}
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont-regular.ttf');  /* 250KB */
  font-weight: 400;
}
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont-medium.ttf');   /* 260KB */
  font-weight: 500;
}
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont-bold.ttf');     /* 270KB */
  font-weight: 700;
}
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont-black.ttf');
  font-weight: 900;
}
/* 5 files × ~250KB = 1.2MB */

✓ After Optimization (85KB total, 93% reduction):

<!-- Preload critical font -->
<link rel="preload" 
      href="/fonts/myfont-regular-latin.woff2" 
      as="font" 
      type="font/woff2" 
      crossorigin>

/* Regular weight, Latin subset only */
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont-regular-latin.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0020-007F, U+00A0-00FF;
}

/* Bold weight, Latin subset only */
@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont-bold-latin.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
  unicode-range: U+0020-007F, U+00A0-00FF;
}

/* Removed unused weights: Light (300), Medium (500), Black (900) */
/* 2 files × ~40KB = 85KB (93% reduction!) */

Performance Impact

File size reduction:1200KB → 85KB (93%)
Load time on 3G:8s → 0.6s
LCP improvement:3.2s → 1.4s
Bandwidth saved per pageview:1.1MB

Summary: Effective Font Size Reduction

Reducing font file sizes is one of the highest-impact performance optimizations you can make. By converting to WOFF2, subsetting to only required characters, removing unused weights, and implementing smart loading strategies, you can achieve 70-95% size reductions with zero visual quality loss.

Start with quick wins (WOFF2 conversion), then move to character subsetting, and finally implement advanced techniques like unicode-range splitting and variable fonts. Test thoroughly, measure impact, and prioritize fonts that load early in the page rendering process. Your users will experience faster load times, and you'll save significant bandwidth costs.

Sarah Mitchell

Written by

Sarah Mitchell

Product Designer, Font Specialist

Marcus Rodriguez

Verified by

Marcus Rodriguez

Lead Developer