Google Fonts: The Developer's Complete Guide
Embed This Widget
Add the script tag and a data attribute to embed this widget.
Embed via iframe for maximum compatibility.
<iframe src="https://fontfyi.com/iframe/entity//" width="420" height="400" frameborder="0" style="border:0;border-radius:10px;max-width:100%" loading="lazy"></iframe>
Paste this URL in WordPress, Medium, or any oEmbed-compatible platform.
https://fontfyi.com/entity//
Add a dynamic SVG badge to your README or docs.
[](https://fontfyi.com/entity//)
Use the native HTML custom element.
Google Fonts: The Developer's Complete Guide
Google Fonts is the most widely used font delivery service on the web, serving billions of font file requests per day. For developers, it offers an extraordinary catalog of high-quality typefaces — including many variable fonts — available with a single line of HTML. But using it well requires understanding the API, the performance trade-offs, and when to move beyond the CDN to self-hosting.
This guide covers everything a developer needs to know: the CSS API v2 syntax, controlling weights and styles, the display parameter, self-hosting for speed and privacy, subset loading for internationalization, and performance best practices.
Google Fonts CSS API v2
The Google Fonts CSS API v2 (launched in 2019) is a significant upgrade over the original API. It uses a cleaner URL structure, supports variable fonts, enables multiple styles in a single request, and provides finer control over weight ranges.
The API endpoint is https://fonts.googleapis.com/css2.
Basic Usage
<!-- Preconnect for performance (always include these) -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- Load Inter Regular (400) -->
<link href="https://fonts.googleapis.com/css2?family=Inter&display=swap" rel="stylesheet">
/* Apply in your CSS */
body {
font-family: 'Inter', sans-serif;
}
API URL Structure
The URL structure for the v2 API:
https://fonts.googleapis.com/css2
?family=FontName:axis@value
&family=AnotherFont:axis@value
&display=swap
Fonts are specified as family parameters. Each can include an axis specification and requested values after @.
Loading Specific Weights and Styles
Static Fonts
For non-variable fonts, you specify weights using wght@:
<!-- Single weight -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400&display=swap" rel="stylesheet">
<!-- Multiple weights -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap" rel="stylesheet">
<!-- Multiple weights, sorted (Google requires sorted order) -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;500;700;900&display=swap" rel="stylesheet">
Italic Styles
Italic styles use the ital axis. Values are 0 (normal) or 1 (italic). When requesting both normal and italic, separate them with a comma inside the weight specification:
<!-- Normal + Italic, one weight each -->
<link href="https://fonts.googleapis.com/css2?family=Lora:ital@0;1&display=swap" rel="stylesheet">
<!-- Multiple weights + italic combinations -->
<!-- Format: ital,wght@0,400;0,700;1,400;1,700 -->
<link href="https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
Important: when requesting both italic and non-italic, the axis order must be alphabetical. So ital,wght — not wght,ital. The values after @ must be sorted tuples (by the first value, then the second).
Multiple Fonts in One Request
Combine multiple fonts in a single request using multiple family parameters. This is more efficient than multiple <link> tags:
<!-- Multiple fonts in one request -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=Lora:ital,wght@0,400;1,400&display=swap" rel="stylesheet">
body {
font-family: 'Inter', sans-serif;
}
blockquote {
font-family: 'Lora', Georgia, serif;
}
Variable Fonts
Variable fonts use a range syntax with two dots:
<!-- Inter variable: full weight range -->
<link href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap" rel="stylesheet">
<!-- Roboto Flex variable: weight + optical size range -->
<link href="https://fonts.googleapis.com/css2?family=Roboto+Flex:opsz,[email protected],100..900&display=swap" rel="stylesheet">
<!-- Source Serif 4: italic + weight + optical size -->
<link href="https://fonts.googleapis.com/css2?family=Source+Serif+4:ital,opsz,wght@0,8..60,200..900;1,8..60,200..900&display=swap" rel="stylesheet">
/* With variable font — any weight in range is valid */
body {
font-family: 'Inter', sans-serif;
font-weight: 400;
}
.ui-medium {
font-weight: 550; /* Not a standard value — works with variable font */
}
h1 {
font-weight: 750;
}
Display Parameter and Font Loading
The display parameter maps directly to the font-display CSS descriptor. It controls the browser's behavior while the font is downloading.
<!-- swap: Show fallback immediately, swap when loaded (recommended) -->
<link href="https://fonts.googleapis.com/css2?family=Inter&display=swap" rel="stylesheet">
<!-- block: Hide text briefly while font loads (FOIT) -->
<link href="https://fonts.googleapis.com/css2?family=Inter&display=block" rel="stylesheet">
<!-- fallback: Very brief FOIT, then fallback. Swap within 3s only -->
<link href="https://fonts.googleapis.com/css2?family=Inter&display=fallback" rel="stylesheet">
<!-- optional: Brief FOIT, then use fallback permanently if not cached -->
<link href="https://fonts.googleapis.com/css2?family=Inter&display=optional" rel="stylesheet">
<!-- auto: Browser decides (not recommended) -->
<link href="https://fonts.googleapis.com/css2?family=Inter&display=auto" rel="stylesheet">
Recommendation for most projects: display=swap. Users always see text (just briefly in the fallback font), and content is never invisible.
Exception: If you have well-matched fallback fonts and most users are repeat visitors (fonts cached), display=optional produces zero layout shift — the font either loads instantly from cache or falls back permanently. An increasingly good choice for performance-critical sites.
How Google Fonts Serves font-display
The CSS returned by the Google Fonts API injects the font-display value into each @font-face block it serves:
/* What Google Fonts returns for display=swap */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/inter/v19/...-subset.woff2) format('woff2');
unicode-range: U+0000-00FF, ...;
}
/* ... more @font-face blocks for other subsets */
Self-Hosting Google Fonts (Privacy and Speed)
Self-hosting means downloading Google Fonts files and serving them from your own server or CDN.
Why Self-Host?
Privacy / GDPR compliance. When a user loads a page that requests Google Fonts, their IP address is sent to Google's servers. For EU users and GDPR compliance, this is a potential legal concern. Self-hosting eliminates the third-party request entirely.
Performance. Self-hosted fonts benefit from:
- Fewer DNS lookups (no fonts.googleapis.com or fonts.gstatic.com)
- Same-origin requests (no CORS pre-flight)
- Your CDN's edge caching behavior, which you control
- rel="preload" in the same document, pointing to files on your domain
Stability. No dependency on Google's CDN availability.
How to Self-Host Google Fonts
The easiest path is the google-webfonts-helper tool, which lets you select fonts, customize subsets, and download ready-to-use WOFF2 files with auto-generated CSS.
- Visit the tool and search for your font (e.g., Inter)
- Select the weights and styles you need
- Choose "modern browsers" to get WOFF2-only files
- Download the zip and place fonts in
/public/fonts/ - Copy the generated CSS into your stylesheet
The generated CSS looks like:
/* self-hosted Inter — generated by google-webfonts-helper */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('/fonts/inter-v19-latin-regular.woff2') format('woff2');
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url('/fonts/inter-v19-latin-700.woff2') format('woff2');
}
Downloading the Variable Font
For variable fonts, download from the Google Fonts page directly:
1. Search for the font on fonts.google.com
2. Select "Download family" → download the TTF/OTF
3. Convert to WOFF2 using woff2_compress (Google's tool) or Transfonter
# Install woff2 tools (macOS)
brew install woff2
# Convert to WOFF2
woff2_compress Inter-VariableFont_wght.ttf
# → Produces Inter-VariableFont_wght.woff2
/* Self-hosted variable font */
@font-face {
font-family: 'Inter';
src: url('/fonts/Inter-VariableFont_wght.woff2') format('woff2');
font-weight: 100 900;
font-style: normal;
font-display: swap;
}
Preload Self-Hosted Fonts
One major advantage of self-hosting: you can preload the critical font file in the <head>:
<head>
<!-- Preload the most critical font file -->
<link
rel="preload"
href="/fonts/inter-regular.woff2"
as="font"
type="font/woff2"
crossorigin
>
<link rel="stylesheet" href="/css/styles.css">
</head>
crossorigin is required even for same-origin font requests when using rel="preload" — this is because fonts are always fetched with CORS mode enabled.
Subset Loading for International Characters
Google Fonts automatically serves subset files based on the unicode-range descriptor and the actual characters present on the page. Each @font-face block in the returned CSS covers a specific character range.
For most projects, you can rely on this subsetting automatically. But for projects targeting specific international audiences, understanding how to optimize matters.
How Google's Automatic Subsetting Works
When the browser encounters a @font-face with unicode-range, it only downloads that file if the page contains characters in that range. For a Latin-only English page loading Roboto, only the Latin subset file downloads, not the Cyrillic or Greek subsets.
<!-- Google handles subsetting automatically for Latin + extended -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
The API returns CSS with multiple @font-face blocks:
- Latin (basic)
- Latin Extended (Polish, Turkish, Vietnamese, etc.)
- Cyrillic
- Cyrillic Extended
- Greek
- Greek Extended
- Vietnamese (sometimes a separate subset)
Requesting Specific Subsets (Legacy v1 API)
The v1 API had an explicit &subset= parameter. In v2, subsetting is automatic — the browser handles it through unicode-range matching. You do not need to specify subsets in v2.
For CJK Languages
For Chinese, Japanese, and Korean fonts, standard subsetting is insufficient. These character sets contain thousands of glyphs, making full font files enormous (500KB+).
Google Fonts serves these through "text" subsetting — a different approach where you specify exactly which characters you need:
<!-- Text-based subsetting: only download glyphs for these characters -->
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&text=サイトタイトル&display=swap" rel="stylesheet">
This is impractical for dynamic content. For CJK content-heavy sites, consider: - Chinese fonts: Source Han Sans, Noto Sans SC/TC, ZCOOL fonts - Japanese: Noto Sans JP, M PLUS fonts - Korean: Noto Sans KR, Nanum fonts
And use Google Fonts' font-display settings combined with generous fallbacks:
/* Japanese with system fallback */
body {
font-family: 'Noto Sans JP', 'Hiragino Kaku Gothic ProN',
'Hiragino Sans', Meiryo, sans-serif;
}
Performance Best Practices
1. Preconnect to Google Fonts Domains
<!-- Critical: add before your Google Fonts link tag -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
The crossorigin attribute on the second preconnect is essential — font files are always fetched with CORS, so the browser needs a CORS-enabled connection to fonts.gstatic.com.
2. Load Only What You Need
Every additional weight and style is another file download. Be deliberate:
<!-- Load only what your design uses -->
<!-- Bad: loading all weights -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet">
<!-- Good: load only what the design actually uses -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<!-- Best: use the variable font for flexibility -->
<link href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap" rel="stylesheet">
3. Use display=swap
Always include &display=swap to prevent invisible text. Never omit this parameter.
4. Combine Multiple Fonts into One Request
<!-- Avoid: two separate requests -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Lora:ital@0;1&display=swap" rel="stylesheet">
<!-- Better: one combined request -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&family=Lora:ital@0;1&display=swap" rel="stylesheet">
5. Use the @import Approach Sparingly
Importing Google Fonts in CSS is less efficient than the HTML <link> approach:
/* Avoid in production — adds latency before fonts start loading */
@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap');
The <link> approach allows the browser to discover and fetch the CSS API response while parsing the <head>, which is earlier in the document lifecycle.
6. Use resource hints wisely
<head>
<!-- Step 1: Preconnect to Google APIs -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- Step 2: Request the font CSS -->
<link href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap" rel="stylesheet">
<!-- Optional: dns-prefetch as fallback for browsers not supporting preconnect -->
<link rel="dns-prefetch" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://fonts.gstatic.com">
</head>
7. Consider Self-Hosting for Critical Fonts
For the primary body font that renders above-the-fold content, self-hosting with rel="preload" is the most performant approach. Combine with Google Fonts CDN for secondary fonts:
<head>
<!-- Self-host + preload the critical body font -->
<link rel="preload" href="/fonts/inter-regular.woff2" as="font" type="font/woff2" crossorigin>
<!-- Use Google Fonts CDN for the display/heading font -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&display=optional" rel="stylesheet">
</head>
The heading font uses display=optional because: (a) headings are less content-critical, (b) the font caches on first visit and loads instantly on subsequent ones, (c) Georgia is an excellent fallback for Playfair Display.
A Complete, Optimized Setup
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Preconnect for Google Fonts CDN -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- Load Inter (variable, primary) + Lora (secondary) -->
<link
href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&family=Lora:ital,wght@0,400;0,700;1,400&display=swap"
rel="stylesheet"
>
<link rel="stylesheet" href="/css/styles.css">
</head>
/* styles.css */
body {
font-family: 'Inter', system-ui, -apple-system, sans-serif;
font-weight: 400;
line-height: 1.6;
}
h1, h2, h3 {
font-family: 'Lora', Georgia, serif;
font-weight: 700;
line-height: 1.2;
}
This setup loads two high-quality Google Fonts in a single optimized request, uses variable font capabilities for Inter, and provides sensible system fallbacks for both.
排版术语
试试这些工具
提及的字体
由Christian Robertson为Google Material Design生态系统设计,这款新格罗特斯克无衬线字体是网页和Android平台上使用最广泛的字体。其双重特性设计在机械精准与自然阅读节奏之间取得平衡,无论是界面标签还是长篇正文都能完美胜任。可变字体支持字宽与字重轴,并涵盖西里尔字母、希腊字母及扩展拉丁脚本。
Steve Matteson精心打造的这款人文主义无衬线字体,凭借直立的笔画应力和开放的字腔,在各类屏幕尺寸和分辨率下均能呈现出色的可读性。作为有史以来部署最广泛的网络字体之一,它以中性专业的气质完美契合正文、电子邮件模板和网页应用。可变字宽与字重轴,加上希伯来语和希腊语支持,使其成为多语言环境下的理想之选。
Rasmus Andersson历经数年专为电脑屏幕精心打磨的这款新格罗特斯克字体,针对数字显示器小字号的高可读性优化了字间距、x字高和笔画对比。光学尺寸轴(opsz)使字体设计在图注与标题之间自动调整,字重轴则覆盖从Thin到Black的全范围。如今它已成为全球仪表盘、文档站点和开发者工具的事实标准选择。
受布宜诺斯艾利斯蒙塞拉特街区几何招牌和店面的启发,Julieta Ulanovsky创作了这款字体,旨在捕捉20世纪初城市字体艺术的精髓。简洁的圆形轮廓和强劲的几何比例赋予其独特的视觉张力,非常适合标题、品牌设计和落地页。可变字重轴覆盖宽广范围,并包含西里尔字母和越南语支持。