Google Fonts:開発者のための完全ガイド
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.
Typography Terms
Try These Tools
Fonts Mentioned
Designed by Christian Robertson for Google's Material Design ecosystem, this neo-grotesque sans-serif is the most widely used typeface on the web and Android. Its dual-nature design balances mechanical precision with natural reading rhythm, making it equally at home in UI labels and long-form text. The variable font supports width and weight axes alongside Cyrillic, Greek, and extended Latin scripts.
Steve Matteson crafted this humanist sans-serif with upright stress and open apertures that prioritize legibility across screen sizes and resolutions. One of the most-deployed web fonts ever published, it strikes a neutral, professional tone well-suited to body copy, email templates, and web applications. Variable width and weight axes, plus Hebrew and Greek script support, make it a versatile multilingual workhorse.
Rasmus Andersson spent years refining this neo-grotesque specifically for computer screens, optimizing letter spacing, x-height, and stroke contrast for high readability at small sizes on digital displays. An optical size axis (opsz) lets the font automatically adjust its design for captions versus headlines, while the weight axis covers the full range from thin to black. It has become the de facto choice for dashboards, documentation sites, and developer tools worldwide.
Inspired by the geometric signage and storefronts of the Montserrat neighborhood in Buenos Aires, Julieta Ulanovsky created this typeface to capture the spirit of early 20th-century urban lettering. Clean circular forms and strong geometric proportions give it an assertive presence ideal for headlines, branding, and landing pages. The variable weight axis spans a wide range, and Cyrillic and Vietnamese scripts are included.