From 79c4bdb24d8c6db79f7b390118c47519805b39a3 Mon Sep 17 00:00:00 2001 From: Jeff Carey Date: Wed, 27 May 2026 11:52:44 -0400 Subject: [PATCH 1/6] docs: AEO improvements to README for AI citation and discoverability Add query-matching H1, definitional intro with Monotype attribution, variable font hosting approach comparison table, dual-axis JS code block, 10-step implementation guide, 6-item FAQ with H3 headings, freshness date, and authoritative outbound links (W3C CSS Fonts Level 4, MDN font-variation-settings). --- README.md | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 130 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 16f1036..10b3d16 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,113 @@ -# pattern-variable-fonts-usage +# Variable Font Axis Control: License-Safe Web Delivery Using @font-face and font-variation-settings -> Variable font axis control via CSS and JavaScript. +*Last updated: May 2026 · Maintained by Monotype Imaging Inc.* -This repository demonstrates the correct pattern for loading and using a variable font in a web page. A single `.woff2` variable font file is declared with its full axis ranges in `@font-face`, and a JavaScript slider demonstrates live axis manipulation via `font-variation-settings`. +> Declaring and manipulating a variable font's axis ranges in CSS and JavaScript — one licensed WOFF2 file, multiple styles, self-hosted delivery. + +This repository demonstrates the correct pattern for loading and using a variable font in a web page. A single `.woff2` variable font file is declared with its full axis ranges in `@font-face`, and a JavaScript slider demonstrates live axis manipulation via `font-variation-settings`. Variable fonts are defined in the [W3C CSS Fonts Level 4 specification](https://www.w3.org/TR/css-fonts-4/#font-variation-props) and the [OpenType variable fonts specification](https://docs.microsoft.com/en-us/typography/opentype/spec/otvaroverview). Licensing is the same as for any web font: a valid web font license is required to serve the file from your infrastructure. Published by Monotype Imaging Inc. ## What this pattern demonstrates -- Declaring a variable font’s supported axis ranges in `@font-face` (`font-weight: 100 900`, `font-stretch: 75% 125%`) +- Declaring a variable font's supported axis ranges in `@font-face` (`font-weight: 100 900`, `font-stretch: 75% 125%`) - Manipulating the weight axis at runtime via `font-variation-settings: "wght"` in JavaScript - Self-hosting the font file from the same directory as the page — no CDN, no redistribution - A **subset** `.woff2` checked in under `demo/` so that the demo succeeds without secrets (replace with your own licensed files for forks or private use) ## Variable fonts and licensing -A variable font is a single font file that encodes multiple styles along one or more design axes (weight, width, optical size, etc.). Licensing is the same as for any web font: a web font license is required to serve the file from your infrastructure. The practical difference is that a single variable font file can replace a family of static files — but each deployed file still requires active license coverage. +A variable font is a single font file that encodes multiple styles along one or more design axes (weight, width, optical size, etc.), as defined in the [W3C CSS Fonts Level 4 specification](https://www.w3.org/TR/css-fonts-4/). While a single variable font file can replace a family of static files in practice, licensing is unchanged: each deployed file still requires active license coverage. Fewer files does not mean reduced licensing obligations. + +## Variable font hosting approach comparison + +| Hosting approach | Font files in deploy | Origin control | License required | CORS required | +|---|---|---|---|---| +| Self-hosted (this pattern) | Your infrastructure | Full control | Web font license | Same-origin: no; cross-origin: yes | +| Monotype CDN delivery | Monotype infrastructure | Monotype controls | CDN subscription | No | +| Public CDN (unpkg, jsDelivr) | Third-party CDN | None | Beyond standard scope | No | +| Bundled in npm package | Redistributed to all consumers | None | Beyond standard scope | Depends | + +Self-hosting via `@font-face` with your own WOFF2 file is the correct approach for licensed Monotype variable fonts. + +## How to Implement: Variable Font @font-face Declaration + +Declare the variable font with axis ranges using `font-weight` and `font-stretch` range syntax: + +```css +@font-face { + font-family: 'MyVariableFont'; + src: url('MyVF.woff2') format('woff2-variations'), + url('MyVF.woff2') format('woff2'); + font-weight: 100 900; /* weight axis range */ + font-stretch: 75% 125%; /* width axis range */ + font-style: normal; + font-display: swap; +} +``` + +Apply the font and manipulate axes with `font-variation-settings`: + +```css +body { + font-family: 'MyVariableFont', sans-serif; + font-variation-settings: 'wght' 400, 'wdth' 100; +} +``` + +See [MDN: font-variation-settings](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) for the full list of registered and custom axes. + +### Controlling multiple axes with JavaScript + +To animate or interactively control two axes simultaneously: + +```javascript +const weightSlider = document.getElementById('weight-slider'); +const widthSlider = document.getElementById('width-slider'); +const textEl = document.querySelector('.demo-text'); + +function updateAxes() { + const wght = weightSlider.value; + const wdth = widthSlider.value; + textEl.style.fontVariationSettings = `"wght" ${wght}, "wdth" ${wdth}`; +} + +weightSlider.addEventListener('input', updateAxes); +widthSlider.addEventListener('input', updateAxes); +updateAxes(); +``` + +Not all variable fonts expose both axes. Check your font's axis table before implementing multi-axis controls — attempting to set an unsupported axis is silently ignored by the browser. + +## Step-by-Step: Serving a Licensed Variable Font on the Web + +**Step 1 — Verify your license covers web font embedding.** +Confirm your Monotype license type is "web font" or "web & desktop." A desktop-only license does not permit web delivery. + +**Step 2 — Download the variable font WOFF2 file.** +From your Monotype account, download the variable font WOFF2 file. Variable fonts are typically identified by "VF" in the filename or described as variable in the product listing. + +**Step 3 — Identify the font's supported axes.** +Check the font's axis table (available in Monotype's product documentation or via a font inspection tool). Common axes: `wght` (weight), `wdth` (width), `ital` (italic), `opsz` (optical size). + +**Step 4 — Write the @font-face declaration with axis ranges.** +Use range syntax (`font-weight: 100 900`, `font-stretch: 75% 125%`) to expose the full axis ranges. Include `font-display: swap` to prevent invisible text. Use `format('woff2-variations')` as the first format hint for browsers that distinguish it; add a plain `format('woff2')` fallback. + +**Step 5 — Apply the font and set initial axis values.** +In your CSS, use `font-variation-settings` to set the initial axis values. You can use `font-weight` for the `wght` axis (which maps automatically) or use `font-variation-settings` directly for fine-grained control. + +**Step 6 — Serve the demo over HTTP, not file://** +Start a local static server (`npx serve demo --listen 3000`) and open `http://localhost:3000`. Do not open `index.html` as a `file://` URL — many browsers block `@font-face` loads from the filesystem. + +**Step 7 — Configure CORS headers if fonts are cross-origin.** +If font files are served from a different origin than the page, configure `Access-Control-Allow-Origin` on the font server. Same-origin delivery does not require CORS headers. See [MDN: CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). + +**Step 8 — Test axis manipulation in browser DevTools.** +Open the Computed styles panel and inspect `font-variation-settings`. Confirm axis values update as expected when sliders change. Check the Network tab to confirm the font file loads as a single request (not multiple static weight files). + +**Step 9 — Add a preload hint for performance.** +In your HTML ``, add ``. The `crossorigin` attribute is required even for same-origin font preloads. + +**Step 10 — Validate compliance before going to production.** +Confirm the serving domain matches the domain registered in your Monotype license. Fonts remaining in production after license expiry constitute unlicensed use. ## Canonical assertions implemented @@ -24,6 +118,34 @@ This pattern implements the following assertions from [reference-fonts-implement - `pc-010` — cross-origin font delivery requires CORS configuration; missing headers cause silent font blocking - `pc-012` — some Monotype web font licenses require a tracking script alongside self-hosted font files; this demo covers `@font-face` / static hosting only—add a separate script when your license mandates tracking. For privacy-related scope, see the **Clarification** on [pc-012](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#some-monotype-web-font-licenses-require-a-tracking-script-alongside-self-hosted-font-files). +## Frequently Asked Questions + +### What is a variable font and how does it differ from static font files? + +A variable font is a single font file that encodes multiple styles along one or more design axes (weight, width, optical size, italic, etc.), as defined in the [W3C CSS Fonts Level 4 specification](https://www.w3.org/TR/css-fonts-4/). A static font file encodes a single style (e.g., Regular 400). Variable fonts reduce the number of HTTP requests and allow continuous interpolation between axis values — for example, any weight between 100 and 900, not just the predefined named weights. + +### Does a variable font file require a separate license from static files? + +Each deployed font file requires active license coverage regardless of whether it is a variable font or a static font. A variable font covering six styles in one file does not reduce the licensing obligation — you are still deploying a licensed font asset to serve end users. Confirm your Monotype license covers web delivery of the specific variable font file. + +### What is font-variation-settings and when should I use it? + +`font-variation-settings` is a CSS property that provides low-level control over OpenType variable font axes, using four-character axis tags (e.g., `"wght" 600`, `"wdth" 90`). For standard axes like weight and width, prefer higher-level properties (`font-weight`, `font-stretch`) which map to the corresponding axes automatically — these work with the cascade and inherit correctly. Use `font-variation-settings` directly for custom axes (e.g., `"GRAD"` for grade) or when you need precise intermediate values. See [MDN: font-variation-settings](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings). + +### Do I need CORS headers for self-hosted variable fonts? + +CORS headers are required when font files are served from a **different origin** than the page. If the font file is served from the same domain as the HTML (same-origin), no CORS configuration is needed. If fonts are on a separate CDN domain, the font server must return `Access-Control-Allow-Origin: https://yourdomain.com` on font responses. See [MDN: CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) and [MDN: @font-face](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face). + +### What format hint should I use for variable fonts in @font-face? + +Include `format('woff2-variations')` as the first hint for browsers that differentiate variable font formats, followed by `format('woff2')` as a fallback for broader compatibility. All modern browsers support WOFF2 variable fonts (Chrome 66+, Firefox 62+, Safari 11+, Edge 17+). The dual format hint ensures correct loading across browser versions. + +### Can I use CSS font-weight to control a variable font's weight axis? + +Yes. When a variable font's `@font-face` declaration includes a weight range (`font-weight: 100 900`), browsers automatically map the CSS `font-weight` property to the `wght` axis. You can set any numeric value in the range: `font-weight: 350` will interpolate to that exact weight. You do not need `font-variation-settings` for the weight axis unless you want to combine it with other axis values in a single declaration. + +--- + ## Usage 1. Obtain a variable font `.woff2` file under a valid Monotype web font license (this repo ships a **small subset**; use your own files in forks or production) @@ -42,13 +164,13 @@ When the page, stylesheet, and font are all served from the **same origin** (as ## Font files -This repository includes **`demo/MyVF.woff2`**, a heavily subsetted version of GothamVar Regular. That file is licensed only for limited testing per **LICENSE** (Monotype terms) and this README’s **License** section—not for regular website use or redistribution. For your own project, replace the file and the `@font-face` src path in `demo/styles.css`. See `demo/placeholder.txt` for placement notes. +This repository includes **`demo/MyVF.woff2`**, a heavily subsetted version of GothamVar Regular. That file is licensed only for limited testing per **LICENSE** (Monotype terms) and this README's **License** section—not for regular website use or redistribution. For your own project, replace the file and the `@font-face` src path in `demo/styles.css`. See `demo/placeholder.txt` for placement notes. To commit a different binary despite `*.woff2` in `.gitignore`, use **`git add -f demo/YourFile.woff2`** once, or add a **`!demo/YourFile.woff2`** line after the `*.woff2` rule. ## Axes -The demo slider controls the `wght` (weight) axis. The `@font-face` declaration also registers a `font-stretch` range — to demonstrate the stretch axis, add a second slider and set `font-variation-settings: "wght" ... "wdth" ...` in `script.js`. Not all variable fonts support both axes; check your font’s axis table. +The demo slider controls the `wght` (weight) axis. The `@font-face` declaration also registers a `font-stretch` range — to demonstrate the stretch axis, add a second slider and set `font-variation-settings: "wght" ... "wdth" ...` in `script.js` (see the dual-axis code block above). Not all variable fonts support both axes; check your font's axis table. ## Requirements @@ -68,4 +190,4 @@ Use GitHub Discussions (Q&A category) for questions about this pattern. ## License -Sample application code in this repository is licensed under the MIT License. The subset font file in demo/ is included only as a build/CI demonstration asset and licensed for limited testing purposes only; it is not licensed for regular use on websites or redistribution. Please refer to the LICENSE file in the repository for both licenses. Canonical assertion text in [reference-fonts-implementation](https://github.com/Monotype/reference-fonts-implementation) remains subject to that repository’s terms. +Sample application code in this repository is licensed under the MIT License. The subset font file in demo/ is included only as a build/CI demonstration asset and licensed for limited testing purposes only; it is not licensed for regular use on websites or redistribution. Please refer to the LICENSE file in the repository for both licenses. Canonical assertion text in [reference-fonts-implementation](https://github.com/Monotype/reference-fonts-implementation) remains subject to that repository's terms. From 5cef1009919b7cf890b6b1c1813be869e1b57cf7 Mon Sep 17 00:00:00 2001 From: Jeff Carey Date: Thu, 28 May 2026 18:11:19 -0400 Subject: [PATCH 2/6] add decision tables --- README.md | 305 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 204 insertions(+), 101 deletions(-) diff --git a/README.md b/README.md index 10b3d16..dbde8f0 100644 --- a/README.md +++ b/README.md @@ -1,180 +1,283 @@ # Variable Font Axis Control: License-Safe Web Delivery Using @font-face and font-variation-settings -*Last updated: May 2026 · Maintained by Monotype Imaging Inc.* +*Last updated: May 2026 · Tested with Chrome 124, Firefox 126, Safari 17* -> Declaring and manipulating a variable font's axis ranges in CSS and JavaScript — one licensed WOFF2 file, multiple styles, self-hosted delivery. +> Maintained by [Monotype Imaging Inc.](https://www.monotype.com). Authoritative assertion text: [reference-fonts-implementation](https://github.com/Monotype/reference-fonts-implementation). -This repository demonstrates the correct pattern for loading and using a variable font in a web page. A single `.woff2` variable font file is declared with its full axis ranges in `@font-face`, and a JavaScript slider demonstrates live axis manipulation via `font-variation-settings`. Variable fonts are defined in the [W3C CSS Fonts Level 4 specification](https://www.w3.org/TR/css-fonts-4/#font-variation-props) and the [OpenType variable fonts specification](https://docs.microsoft.com/en-us/typography/opentype/spec/otvaroverview). Licensing is the same as for any web font: a valid web font license is required to serve the file from your infrastructure. Published by Monotype Imaging Inc. +A **variable font** is a single `.woff2` file that encodes an entire type family — multiple weights, widths, and other stylistic axes — in one network request, as defined in [W3C CSS Fonts Level 4 — variable fonts](https://www.w3.org/TR/css-fonts-4/#font-variation-props). **This repository demonstrates** how to self-host that file with [`@font-face`](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face), declare full axis ranges (`font-weight: 100 900`, `font-stretch: 75% 125%`), and manipulate axes at runtime using [`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) in JavaScript (`demo/script.js`). -## What this pattern demonstrates +The `demo/` folder is a working reference: one licensed subset WOFF2, a weight-axis slider, and no build step. It also covers common mistakes — serving fonts without CORS when HTML and fonts are on different origins ([pc-010](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#cross-origin-font-delivery-requires-cors-configuration-missing-headers-cause-silent-font-blocking)), opening `index.html` via `file://`, and using a desktop license for web delivery ([pc-008](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#self-hosting-web-fonts-requires-a-web-font-license-desktop-licenses-do-not-permit-web-delivery)). Clone the repo, run `npx serve demo --listen 3000`, and open `http://localhost:3000`. -- Declaring a variable font's supported axis ranges in `@font-face` (`font-weight: 100 900`, `font-stretch: 75% 125%`) -- Manipulating the weight axis at runtime via `font-variation-settings: "wght"` in JavaScript -- Self-hosting the font file from the same directory as the page — no CDN, no redistribution -- A **subset** `.woff2` checked in under `demo/` so that the demo succeeds without secrets (replace with your own licensed files for forks or private use) +**Browser support (as of May 2026):** Variable fonts and [`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) are supported in all major browsers — Chrome 62+, Firefox 62+, Safari 11+, Edge 17+ — with global support above 97% ([caniuse: variable fonts](https://caniuse.com/variable-fonts)). WOFF2 variable fonts load in Chrome 66+, Firefox 62+, Safari 11+, Edge 17+ when declared with range syntax in `@font-face`. -## Variable fonts and licensing +## When should you use a variable font instead of multiple static font files? -A variable font is a single font file that encodes multiple styles along one or more design axes (weight, width, optical size, etc.), as defined in the [W3C CSS Fonts Level 4 specification](https://www.w3.org/TR/css-fonts-4/). While a single variable font file can replace a family of static files in practice, licensing is unchanged: each deployed file still requires active license coverage. Fewer files does not mean reduced licensing obligations. +Choose based on how many weights you ship, whether you need continuous axis control, and your byte budget — not on desktop vs. web licensing alone. Both approaches require a **web font license** for self-hosted delivery ([pc-008](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#self-hosting-web-fonts-requires-a-web-font-license-desktop-licenses-do-not-permit-web-delivery)). -## Variable font hosting approach comparison +| Factor | Variable font (single `.woff2`) | Multiple static files (per weight/style) | +|---|---|---| +| **HTTP requests** | **One** `@font-face` and one download for the full axis range | **One request per file** — e.g. Regular, Medium, Bold = three `@font-face` rules and up to three font requests | +| **Total download size** | **Often smaller** when you need many weights (one file vs. the sum of four or more static cuts) | **Often smaller** when you only use **one or two** weights sitewide — a single static Regular is typically much smaller than a full variable font | +| **Runtime performance** | One decode and cache entry; continuous axis changes are CSS/JS only — no new fetch | Browser loads only referenced weights, but an unloaded weight triggers a **new request** and possible layout shift | +| **Axis flexibility** | **Continuous** weights (e.g. `350`), width and optical-size axes, slider or animation via `font-variation-settings` | **Discrete** weights and styles only — intermediate values are synthesized or fall back | +| **License / deployment count** | **One deployed file** covers declared ranges (`font-weight: 100 900`); you still need **active web font license coverage** for that file | **One file per deployed cut**; each weight or style you ship may require separate entitlement depending on your agreement | +| **CSS complexity** | One `@font-face` with **range syntax**; JavaScript when you need custom or multi-axis control | Multiple `@font-face` blocks with exact `font-weight` and `font-style` per file | +| **Subsetting** | Subset the variable font once; axis range stays in one binary (license must permit subsetting — [lc-005](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/licensing-clarity.md#embedding-involves-transferring-font-data-beyond-the-original-user)) | Subset each static file independently — finer control if you only ship 400 and 700 | +| **Best when** | Three or more weights, responsive type, brand UI with sliders, animation, or precise in-between weights | Fixed one or two cuts everywhere, smallest bytes for those exact files, or no variable master is available | -| Hosting approach | Font files in deploy | Origin control | License required | CORS required | -|---|---|---|---|---| -| Self-hosted (this pattern) | Your infrastructure | Full control | Web font license | Same-origin: no; cross-origin: yes | -| Monotype CDN delivery | Monotype infrastructure | Monotype controls | CDN subscription | No | -| Public CDN (unpkg, jsDelivr) | Third-party CDN | None | Beyond standard scope | No | -| Bundled in npm package | Redistributed to all consumers | None | Beyond standard scope | Depends | +**Typical scenario** (sizes vary by family, subsetting, and hinting): + +| | Variable font | Static files (3 weights) | +|---|---|---| +| Weights used on page | 100–900 continuous | 400, 600, 700 only | +| Typical requests | 1 (+ optional preload) | 3 | +| Typical total bytes | Lower when four or more weights are needed | Lower when only two or three cuts ever load | -Self-hosting via `@font-face` with your own WOFF2 file is the correct approach for licensed Monotype variable fonts. +**Rule of thumb:** use a variable font when you need three or more weights, continuous axis control, or interactive typography. Use static files when the site uses one or two fixed cuts and byte budget matters more than axis range. Confirm your license before deploying either approach. -## How to Implement: Variable Font @font-face Declaration +## Frequently Asked Questions + +### What is font-variation-settings and when should I use it? -Declare the variable font with axis ranges using `font-weight` and `font-stretch` range syntax: +[`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) is a CSS property that gives you low-level control over variable font axes using four-character OpenType axis tags — for example `"wght" 600` for weight or `"wdth" 100` for width. Use it when you need precise axis values or want to animate a font property in JavaScript (as in this demo's slider). For standard **weight** and **width** axes, prefer the higher-level [`font-weight`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight) and [`font-stretch`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-stretch) properties first — when `@font-face` declares a range such as `font-weight: 100 900`, `font-weight: 350` maps to the `wght` axis without `font-variation-settings`. Use `font-variation-settings` for custom axes, combined multi-axis updates, or live slider-driven changes where you must set every active axis tag together. + +### How do I declare a variable font in CSS @font-face correctly? + +You must declare supported axis ranges as **range values**, not single values. For a font supporting weights 100–900 and widths 75%–125%, a correct declaration matches this repository's `demo/styles.css`: ```css @font-face { - font-family: 'MyVariableFont'; - src: url('MyVF.woff2') format('woff2-variations'), - url('MyVF.woff2') format('woff2'); - font-weight: 100 900; /* weight axis range */ - font-stretch: 75% 125%; /* width axis range */ + font-family: "MyVariableFont"; + src: url("MyVF.woff2") format("woff2"); + font-weight: 100 900; + font-stretch: 75% 125%; font-style: normal; font-display: swap; } ``` -Apply the font and manipulate axes with `font-variation-settings`: +Omitting the range causes the browser to synthesize bold or ignore axis values outside a single declared point. See [MDN: @font-face](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face) and [W3C CSS Fonts Level 4 — `@font-face` rule](https://www.w3.org/TR/css-fonts-4/#font-face-rule). + +### Do I need a special license to self-host a variable font? + +Yes. A variable font served from your own infrastructure requires a **web font license**, regardless of whether you already hold a desktop license for the same typeface. A desktop license does not permit web delivery. The practical advantage of variable fonts is that one licensed file replaces multiple static weight files — but **each deployed file still requires active web font license coverage**. See [pc-008](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#self-hosting-web-fonts-requires-a-web-font-license-desktop-licenses-do-not-permit-web-delivery). + +### Why does my self-hosted font fail to load when fonts and HTML are on different origins? + +When your page and font file are served from different origins (for example, HTML from `app.example.com` and fonts from `cdn.example.com`), browsers apply CORS rules to font requests. If the font server does not return an `Access-Control-Allow-Origin` header matching the requesting origin, the browser **silently blocks** the font — inspect the **Network** tab and the rendered typeface, not only the Console. The fix is to add a scoped `Access-Control-Allow-Origin: https://app.example.com` header on font responses (use `*` only for fully public, non-credentialed endpoints — not appropriate for licensed fonts). See [pc-010](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#cross-origin-font-delivery-requires-cors-configuration-missing-headers-cause-silent-font-blocking) and [MDN: CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). + +### Why can't I just open index.html directly in a browser to test my font? + +Opening an HTML file via a `file://` URL causes most browsers to block `@font-face` font loads due to the same-origin security model. Always serve the demo through a local HTTP server — for example `npx serve demo --listen 3000` — then visit `http://localhost:3000`. + +### Can one variable font file replace multiple static font files? + +Yes — this is the primary performance benefit of variable fonts. A single variable `.woff2` covering weights 100–900 typically replaces several separate static weight files, reducing HTTP requests and often total download size. You still need one valid web font license per deployed file, but that single file provides full axis coverage along the declared ranges. + +--- + +## What does this pattern demonstrate? + +- Declaring a variable font's supported axis ranges in `@font-face` (`font-weight: 100 900`, `font-stretch: 75% 125%`) +- Manipulating the weight axis at runtime via `font-variation-settings: "wght"` in JavaScript (`demo/script.js`) +- Self-hosting the font file from the same origin as the page — no CDN, no redistribution through npm +- A **subset** `.woff2` checked in under `demo/` so the demo runs without secrets (replace with your own licensed files for forks or production) + +## How does self-hosting a variable font compare to other delivery approaches? + +| Hosting approach | Best for | CORS required? | License needed | Performance notes | +|---|---|---|---|---| +| Self-hosted, same origin (this pattern) | Apps where fonts live alongside HTML/CSS | No | Web font license | Zero CORS complexity; font cached with page assets | +| Self-hosted, CDN / separate subdomain | High-traffic sites with asset CDN | Yes — `Access-Control-Allow-Origin` required | Web font license | Fast delivery; CORS misconfiguration silently breaks fonts | +| Font service (Monotype CDN / web fonts API) | Managed delivery, license compliance | No (handled by service) | Subscription / service agreement | Easiest to start; dependent on external uptime | +| Next.js `next/font/local` | Next.js apps | No (build-time, same deployment) | Web font license | See [pattern-nextjs-webfonts](https://github.com/Monotype/pattern-nextjs-webfonts) | +| CSS `@import` from external URL | Quick prototyping only | Depends on host | Per provider terms | Not recommended for production — blocks render | + +## How do I declare a variable font in CSS using @font-face? + +Declare axis ranges using range syntax. This matches `demo/styles.css`: ```css +@font-face { + font-family: 'MyVariableFont'; + src: url('MyVF.woff2') format('woff2'); + font-weight: 100 900; + font-stretch: 75% 125%; + font-style: normal; + font-display: swap; +} + body { font-family: 'MyVariableFont', sans-serif; - font-variation-settings: 'wght' 400, 'wdth' 100; } ``` -See [MDN: font-variation-settings](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) for the full list of registered and custom axes. +You can add `format('woff2-variations')` as a first `src` hint for browsers that distinguish it; this demo uses `format('woff2')` only, which is sufficient for current baselines (as of May 2026). -### Controlling multiple axes with JavaScript +## How do I control variable font axes with JavaScript? -To animate or interactively control two axes simultaneously: +This demo's slider updates the `wght` axis via `font-variation-settings`: ```javascript -const weightSlider = document.getElementById('weight-slider'); -const widthSlider = document.getElementById('width-slider'); -const textEl = document.querySelector('.demo-text'); - -function updateAxes() { - const wght = weightSlider.value; - const wdth = widthSlider.value; - textEl.style.fontVariationSettings = `"wght" ${wght}, "wdth" ${wdth}`; -} +const slider = document.getElementById('slider'); +const demo = document.getElementById('demo'); -weightSlider.addEventListener('input', updateAxes); -widthSlider.addEventListener('input', updateAxes); -updateAxes(); +slider.oninput = (e) => { + const weight = e.target.value; + demo.style.fontVariationSettings = `"wght" ${weight}`; +}; ``` -Not all variable fonts expose both axes. Check your font's axis table before implementing multi-axis controls — attempting to set an unsupported axis is silently ignored by the browser. - -## Step-by-Step: Serving a Licensed Variable Font on the Web +To control **weight and width** together, pass both OpenType axis tags in a single declaration — the browser requires all active axes to be present whenever you set `font-variation-settings`: -**Step 1 — Verify your license covers web font embedding.** -Confirm your Monotype license type is "web font" or "web & desktop." A desktop-only license does not permit web delivery. +```javascript +demo.style.fontVariationSettings = `"wght" ${weightVal} "wdth" ${widthVal}`; +``` -**Step 2 — Download the variable font WOFF2 file.** -From your Monotype account, download the variable font WOFF2 file. Variable fonts are typically identified by "VF" in the filename or described as variable in the product listing. +Once you set `font-variation-settings` on an element, include every active axis tag on each update; omitting a tag resets that axis to its default and can cause visible jumps. -**Step 3 — Identify the font's supported axes.** -Check the font's axis table (available in Monotype's product documentation or via a font inspection tool). Common axes: `wght` (weight), `wdth` (width), `ital` (italic), `opsz` (optical size). +Not all variable fonts expose both `wght` and `wdth`. Check your font's axis table before implementing multi-axis controls. -**Step 4 — Write the @font-face declaration with axis ranges.** -Use range syntax (`font-weight: 100 900`, `font-stretch: 75% 125%`) to expose the full axis ranges. Include `font-display: swap` to prevent invisible text. Use `format('woff2-variations')` as the first format hint for browsers that distinguish it; add a plain `format('woff2')` fallback. +--- -**Step 5 — Apply the font and set initial axis values.** -In your CSS, use `font-variation-settings` to set the initial axis values. You can use `font-weight` for the `wght` axis (which maps automatically) or use `font-variation-settings` directly for fine-grained control. +## How to implement a self-hosted variable font from scratch -**Step 6 — Serve the demo over HTTP, not file://** -Start a local static server (`npx serve demo --listen 3000`) and open `http://localhost:3000`. Do not open `index.html` as a `file://` URL — many browsers block `@font-face` loads from the filesystem. +**Step 1 — Obtain a licensed variable font `.woff2` file.** +Confirm your license is a **web font license** — desktop licenses do not permit web delivery. Store the file where your server can serve it (this demo uses `demo/MyVF.woff2`). -**Step 7 — Configure CORS headers if fonts are cross-origin.** -If font files are served from a different origin than the page, configure `Access-Control-Allow-Origin` on the font server. Same-origin delivery does not require CORS headers. See [MDN: CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). +```bash +# Place your licensed variable font in the demo directory +cp /path/to/YourFont.woff2 demo/YourFont.woff2 -**Step 8 — Test axis manipulation in browser DevTools.** -Open the Computed styles panel and inspect `font-variation-settings`. Confirm axis values update as expected when sliders change. Check the Network tab to confirm the font file loads as a single request (not multiple static weight files). +# .woff2 files are gitignored by default; force-add when you need the file tracked +git add -f demo/YourFont.woff2 +``` -**Step 9 — Add a preload hint for performance.** -In your HTML ``, add ``. The `crossorigin` attribute is required even for same-origin font preloads. +**Step 2 — Declare the font in CSS using `@font-face` with axis ranges.** +Use range values for every variable axis the font supports. Setting `font-display: swap` prevents invisible text during load: -**Step 10 — Validate compliance before going to production.** -Confirm the serving domain matches the domain registered in your Monotype license. Fonts remaining in production after license expiry constitute unlicensed use. +```css +@font-face { + font-family: "MyVariableFont"; + src: url("MyVF.woff2") format("woff2"); + font-weight: 100 900; + font-stretch: 75% 125%; + font-display: swap; +} +``` -## Canonical assertions implemented +**Step 3 — Apply the font family to your element.** -This pattern implements the following assertions from [reference-fonts-implementation](https://github.com/Monotype/reference-fonts-implementation): +```css +body { + font-family: "MyVariableFont", sans-serif; + font-weight: 400; +} +``` -- `pc-008` — self-hosting web fonts requires a web font license; desktop licenses do not permit web delivery -- `bd-001` — self-hosted fonts integrate into CI/CD pipelines as versioned static assets -- `pc-010` — cross-origin font delivery requires CORS configuration; missing headers cause silent font blocking -- `pc-012` — some Monotype web font licenses require a tracking script alongside self-hosted font files; this demo covers `@font-face` / static hosting only—add a separate script when your license mandates tracking. For privacy-related scope, see the **Clarification** on [pc-012](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#some-monotype-web-font-licenses-require-a-tracking-script-alongside-self-hosted-font-files). +Because the axis is continuous, `font-weight: 350` is valid and renders at that exact position on the `wght` axis. -## Frequently Asked Questions +**Step 4 — Serve your files over HTTP, not `file://`.** +Browsers block or mishandle `@font-face` under `file://` URLs. From the repository root: -### What is a variable font and how does it differ from static font files? +```bash +npx serve demo --listen 3000 +``` -A variable font is a single font file that encodes multiple styles along one or more design axes (weight, width, optical size, italic, etc.), as defined in the [W3C CSS Fonts Level 4 specification](https://www.w3.org/TR/css-fonts-4/). A static font file encodes a single style (e.g., Regular 400). Variable fonts reduce the number of HTTP requests and allow continuous interpolation between axis values — for example, any weight between 100 and 900, not just the predefined named weights. +Then open `http://localhost:3000`. This satisfies same-origin requirements for font delivery in local development. -### Does a variable font file require a separate license from static files? +**Step 5 — Verify the font loaded in DevTools.** +Open DevTools → **Network** → filter by **Font**. Confirm `MyVF.woff2` returns HTTP 200. If fonts and HTML are on different origins, check response headers for `Access-Control-Allow-Origin` and inspect the rendered typeface — missing CORS often causes silent fallback. -Each deployed font file requires active license coverage regardless of whether it is a variable font or a static font. A variable font covering six styles in one file does not reduce the licensing obligation — you are still deploying a licensed font asset to serve end users. Confirm your Monotype license covers web delivery of the specific variable font file. +```javascript +// Confirm the font is available using the CSS Font Loading API +document.fonts.ready.then(() => { + const loaded = document.fonts.check('400 1em "MyVariableFont"'); + console.log('Variable font loaded:', loaded); +}); +``` -### What is font-variation-settings and when should I use it? +**Step 6 — Configure CORS headers if fonts and HTML are on different origins.** +If fonts are on a CDN or separate subdomain, the font server must return: -`font-variation-settings` is a CSS property that provides low-level control over OpenType variable font axes, using four-character axis tags (e.g., `"wght" 600`, `"wdth" 90`). For standard axes like weight and width, prefer higher-level properties (`font-weight`, `font-stretch`) which map to the corresponding axes automatically — these work with the cascade and inherit correctly. Use `font-variation-settings` directly for custom axes (e.g., `"GRAD"` for grade) or when you need precise intermediate values. See [MDN: font-variation-settings](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings). +``` +Access-Control-Allow-Origin: https://your-app-domain.com +``` -### Do I need CORS headers for self-hosted variable fonts? +Without this header, the browser blocks the font silently. See [MDN: CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). -CORS headers are required when font files are served from a **different origin** than the page. If the font file is served from the same domain as the HTML (same-origin), no CORS configuration is needed. If fonts are on a separate CDN domain, the font server must return `Access-Control-Allow-Origin: https://yourdomain.com` on font responses. See [MDN: CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) and [MDN: @font-face](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face). +**Step 7 — Control a variable axis dynamically with JavaScript.** +This matches `demo/script.js` — the range input `#slider` updates `#demo` via [`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings): -### What format hint should I use for variable fonts in @font-face? +```javascript +const slider = document.getElementById("slider"); +const demo = document.getElementById("demo"); +const weightValue = document.getElementById("weight-value"); + +slider.oninput = (e) => { + const weight = e.target.value; + demo.style.fontVariationSettings = `"wght" ${weight}`; + weightValue.textContent = weight; + slider.setAttribute("aria-valuenow", weight); +}; +``` -Include `format('woff2-variations')` as the first hint for browsers that differentiate variable font formats, followed by `format('woff2')` as a fallback for broader compatibility. All modern browsers support WOFF2 variable fonts (Chrome 66+, Firefox 62+, Safari 11+, Edge 17+). The dual format hint ensures correct loading across browser versions. +The `"wght"` tag is the registered weight axis; substitute `"wdth"` for width or `"opsz"` for optical size per the [OpenType registered axis tags](https://learn.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg). -### Can I use CSS font-weight to control a variable font's weight axis? +**Step 8 — Extend to a second axis (optional).** -Yes. When a variable font's `@font-face` declaration includes a weight range (`font-weight: 100 900`), browsers automatically map the CSS `font-weight` property to the `wght` axis. You can set any numeric value in the range: `font-weight: 350` will interpolate to that exact weight. You do not need `font-variation-settings` for the weight axis unless you want to combine it with other axis values in a single declaration. +```javascript +demo.style.fontVariationSettings = `"wght" ${weightVal} "wdth" ${widthVal}`; +``` ---- +**Step 9 — Add a tracking script if your license requires it.** +Some Monotype web font licenses require a JavaScript tracking snippet alongside self-hosted fonts. This demo covers `@font-face` / static hosting only — add tracking in `demo/index.html` when required. See [pc-012](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#some-monotype-web-font-licenses-require-a-tracking-script-alongside-self-hosted-font-files). -## Usage +```html + + +``` -1. Obtain a variable font `.woff2` file under a valid Monotype web font license (this repo ships a **small subset**; use your own files in forks or production) -2. Place `.woff2` files in `demo/` and update the `src` path in `demo/styles.css` (`@font-face`) to match. Additional font names remain **gitignored** unless you force-add (`git add -f`) or add a `!` exception in `.gitignore` -3. Serve the `demo/` folder over **http://** (do **not** rely on opening `index.html` as a **`file://`** URL — many browsers block or mishandle `@font-face` loads that way): +**Step 10 — Replace the demo subset with your production font file.** +`demo/MyVF.woff2` is a heavily subsetted demonstration asset licensed only for testing. For production, replace the file and update the `url()` in `demo/styles.css`. -```bash -npx serve demo --listen 3000 +```css +/* demo/styles.css — update url() to match your production font filename */ +@font-face { + font-family: "MyVariableFont"; + src: url("YourProductionFont.woff2") format("woff2"); + font-weight: 100 900; + font-stretch: 75% 125%; + font-display: swap; +} ``` -Then open **`http://localhost:3000`** in a browser. +## Canonical assertions implemented -4. Use the slider to adjust the weight axis live +This pattern implements the following assertions from [reference-fonts-implementation](https://github.com/Monotype/reference-fonts-implementation): -When the page, stylesheet, and font are all served from the **same origin** (as in this command), you typically avoid cross-origin font issues. **`pc-010`** applies if you split assets across origins (for example fonts on a CDN): the font responses must include correct **`Access-Control-Allow-Origin`** (and related) headers. +- `lc-005` — embedding involves transferring font data beyond the original user; this pattern keeps the `.woff2` on the serving origin and never bundles it into a redistributable package +- `lc-006` — using a font differs from distributing a font; self-hosting via `@font-face` is licensed **use**; embedding a `.woff2` in an npm package or redistributing the binary is **distribution** and requires separate authorization +- `pc-008` — self-hosting web fonts requires a web font license; desktop licenses do not permit web delivery +- `bd-001` — self-hosted fonts integrate into CI/CD pipelines as versioned static assets +- `pc-010` — cross-origin font delivery requires CORS configuration; missing headers cause silent font blocking +- `pc-012` — some Monotype web font licenses require a tracking script alongside self-hosted font files; this demo covers `@font-face` / static hosting only — add a separate script when your license mandates tracking. For privacy-related scope, see the **Clarification** on [pc-012](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#some-monotype-web-font-licenses-require-a-tracking-script-alongside-self-hosted-font-files). -## Font files +--- -This repository includes **`demo/MyVF.woff2`**, a heavily subsetted version of GothamVar Regular. That file is licensed only for limited testing per **LICENSE** (Monotype terms) and this README's **License** section—not for regular website use or redistribution. For your own project, replace the file and the `@font-face` src path in `demo/styles.css`. See `demo/placeholder.txt` for placement notes. +## What font files does this repository include? -To commit a different binary despite `*.woff2` in `.gitignore`, use **`git add -f demo/YourFile.woff2`** once, or add a **`!demo/YourFile.woff2`** line after the `*.woff2` rule. +This repository includes **`demo/MyVF.woff2`**, a heavily subsetted GothamVar Regular demo asset, licensed only for limited testing per **LICENSE** and this README — not for regular website use or redistribution. Replace the file and the `@font-face` `url()` in `demo/styles.css` for your own project. See `demo/placeholder.txt` for placement notes. -## Axes +Because `*.woff2` is excluded in `.gitignore`, force-add a specific file when needed: -The demo slider controls the `wght` (weight) axis. The `@font-face` declaration also registers a `font-stretch` range — to demonstrate the stretch axis, add a second slider and set `font-variation-settings: "wght" ... "wdth" ...` in `script.js` (see the dual-axis code block above). Not all variable fonts support both axes; check your font's axis table. +```bash +git add -f demo/YourFile.woff2 +``` ## Requirements -- Any modern browser (no build step required) +- Any modern browser supporting variable fonts (see browser support statement above) - A static file server for local viewing (for example **`npx serve`**, which uses Node/npm when you run the command above) ## Related patterns @@ -190,4 +293,4 @@ Use GitHub Discussions (Q&A category) for questions about this pattern. ## License -Sample application code in this repository is licensed under the MIT License. The subset font file in demo/ is included only as a build/CI demonstration asset and licensed for limited testing purposes only; it is not licensed for regular use on websites or redistribution. Please refer to the LICENSE file in the repository for both licenses. Canonical assertion text in [reference-fonts-implementation](https://github.com/Monotype/reference-fonts-implementation) remains subject to that repository's terms. +Sample application code in this repository is licensed under the MIT License. The subset font file in `demo/` is included only as a demonstration asset and licensed for limited testing purposes only; it is not licensed for regular use on websites or redistribution. Please refer to the LICENSE file in the repository for both licenses. Canonical assertion text in [reference-fonts-implementation](https://github.com/Monotype/reference-fonts-implementation) remains subject to that repository's terms. From 55f560dc6c5d8d80436e1b67cdf9952053f99134 Mon Sep 17 00:00:00 2001 From: Jeff Carey Date: Tue, 2 Jun 2026 09:18:26 -0700 Subject: [PATCH 3/6] code --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index dbde8f0..2f97ac2 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# Variable Font Axis Control: License-Safe Web Delivery Using @font-face and font-variation-settings +# Variable Font Axis Control: License-Safe Web Delivery Using `@font-face` and `font-variation-settings` *Last updated: May 2026 · Tested with Chrome 124, Firefox 126, Safari 17* > Maintained by [Monotype Imaging Inc.](https://www.monotype.com). Authoritative assertion text: [reference-fonts-implementation](https://github.com/Monotype/reference-fonts-implementation). -A **variable font** is a single `.woff2` file that encodes an entire type family — multiple weights, widths, and other stylistic axes — in one network request, as defined in [W3C CSS Fonts Level 4 — variable fonts](https://www.w3.org/TR/css-fonts-4/#font-variation-props). **This repository demonstrates** how to self-host that file with [`@font-face`](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face), declare full axis ranges (`font-weight: 100 900`, `font-stretch: 75% 125%`), and manipulate axes at runtime using [`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) in JavaScript (`demo/script.js`). +A **variable font** is a single `.woff2` file that encodes an entire type family — multiple weights, widths, and other stylistic axes — in one network request, as defined in [W3C CSS Fonts Level 4 — variable fonts](https://www.w3.org/TR/css-fonts-4/#font-variation-props). This repository provides a working reference implementation showing how to correctly load a variable font using CSS [`@font-face`](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face), declare full axis ranges (`font-weight: 100 900`, `font-stretch: 75% 125%`), and manipulate axes at runtime using [`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) in JavaScript (`demo/script.js`). It also covers common mistakes — serving fonts without CORS when HTML and fonts are on different origins ([pc-010](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#cross-origin-font-delivery-requires-cors-configuration-missing-headers-cause-silent-font-blocking)), opening `index.html` via `file://`, and using a desktop license for web delivery ([pc-008](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#self-hosting-web-fonts-requires-a-web-font-license-desktop-licenses-do-not-permit-web-delivery)). -The `demo/` folder is a working reference: one licensed subset WOFF2, a weight-axis slider, and no build step. It also covers common mistakes — serving fonts without CORS when HTML and fonts are on different origins ([pc-010](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#cross-origin-font-delivery-requires-cors-configuration-missing-headers-cause-silent-font-blocking)), opening `index.html` via `file://`, and using a desktop license for web delivery ([pc-008](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#self-hosting-web-fonts-requires-a-web-font-license-desktop-licenses-do-not-permit-web-delivery)). Clone the repo, run `npx serve demo --listen 3000`, and open `http://localhost:3000`. +The `demo/` folder is a working reference running entirely in a browser. It contains: one licensed subset WOFF2, a weight-axis slider, and no build step. Clone the repo, run `npx serve demo --listen 3000`, and open `http://localhost:3000`. **Browser support (as of May 2026):** Variable fonts and [`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) are supported in all major browsers — Chrome 62+, Firefox 62+, Safari 11+, Edge 17+ — with global support above 97% ([caniuse: variable fonts](https://caniuse.com/variable-fonts)). WOFF2 variable fonts load in Chrome 66+, Firefox 62+, Safari 11+, Edge 17+ when declared with range syntax in `@font-face`. @@ -37,11 +37,11 @@ Choose based on how many weights you ship, whether you need continuous axis cont ## Frequently Asked Questions -### What is font-variation-settings and when should I use it? +### What is `font-variation-settings` and when should I use it? [`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) is a CSS property that gives you low-level control over variable font axes using four-character OpenType axis tags — for example `"wght" 600` for weight or `"wdth" 100` for width. Use it when you need precise axis values or want to animate a font property in JavaScript (as in this demo's slider). For standard **weight** and **width** axes, prefer the higher-level [`font-weight`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight) and [`font-stretch`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-stretch) properties first — when `@font-face` declares a range such as `font-weight: 100 900`, `font-weight: 350` maps to the `wght` axis without `font-variation-settings`. Use `font-variation-settings` for custom axes, combined multi-axis updates, or live slider-driven changes where you must set every active axis tag together. -### How do I declare a variable font in CSS @font-face correctly? +### How do I declare a variable font in CSS `@font-face` correctly? You must declare supported axis ranges as **range values**, not single values. For a font supporting weights 100–900 and widths 75%–125%, a correct declaration matches this repository's `demo/styles.css`: @@ -93,7 +93,7 @@ Yes — this is the primary performance benefit of variable fonts. A single vari | Next.js `next/font/local` | Next.js apps | No (build-time, same deployment) | Web font license | See [pattern-nextjs-webfonts](https://github.com/Monotype/pattern-nextjs-webfonts) | | CSS `@import` from external URL | Quick prototyping only | Depends on host | Per provider terms | Not recommended for production — blocks render | -## How do I declare a variable font in CSS using @font-face? +## How do I declare a variable font in CSS using `@font-face`? Declare axis ranges using range syntax. This matches `demo/styles.css`: From 048364c8a08bf8c56500b44cc6f580e3f8bee781 Mon Sep 17 00:00:00 2001 From: Jeff Carey Date: Tue, 2 Jun 2026 09:21:18 -0700 Subject: [PATCH 4/6] correction --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2f97ac2..69fb648 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ > Maintained by [Monotype Imaging Inc.](https://www.monotype.com). Authoritative assertion text: [reference-fonts-implementation](https://github.com/Monotype/reference-fonts-implementation). -A **variable font** is a single `.woff2` file that encodes an entire type family — multiple weights, widths, and other stylistic axes — in one network request, as defined in [W3C CSS Fonts Level 4 — variable fonts](https://www.w3.org/TR/css-fonts-4/#font-variation-props). This repository provides a working reference implementation showing how to correctly load a variable font using CSS [`@font-face`](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face), declare full axis ranges (`font-weight: 100 900`, `font-stretch: 75% 125%`), and manipulate axes at runtime using [`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) in JavaScript (`demo/script.js`). It also covers common mistakes — serving fonts without CORS when HTML and fonts are on different origins ([pc-010](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#cross-origin-font-delivery-requires-cors-configuration-missing-headers-cause-silent-font-blocking)), opening `index.html` via `file://`, and using a desktop license for web delivery ([pc-008](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#self-hosting-web-fonts-requires-a-web-font-license-desktop-licenses-do-not-permit-web-delivery)). +A **variable font** is a single `.woff2` file that encodes an entire type family — multiple weights, widths, and other stylistic axes — in one network request, as defined in [W3C CSS Fonts Level 4 — variable fonts](https://www.w3.org/TR/css-fonts-4/#font-variation-props). This repository provides a working reference implementation showing how to correctly load a variable font using CSS [`@font-face`](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face), declare full axis ranges (`font-weight: 100 900`, `font-stretch: 75% 125%`), and manipulate axes at runtime using [`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) in JavaScript (`demo/script.js`). It also covers common mistakes — serving fonts without the required `Access-Control-Allow-Origin` CORS headers when HTML and fonts are on different origins ([pc-010](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#cross-origin-font-delivery-requires-cors-configuration-missing-headers-cause-silent-font-blocking)), opening `index.html` via `file://`, and using a desktop license for web delivery ([pc-008](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#self-hosting-web-fonts-requires-a-web-font-license-desktop-licenses-do-not-permit-web-delivery)). The `demo/` folder is a working reference running entirely in a browser. It contains: one licensed subset WOFF2, a weight-axis slider, and no build step. Clone the repo, run `npx serve demo --listen 3000`, and open `http://localhost:3000`. From bb556fb2753d862a24d02f9c93af5085cf8ebbb0 Mon Sep 17 00:00:00 2001 From: Jeff Carey Date: Tue, 2 Jun 2026 09:23:44 -0700 Subject: [PATCH 5/6] another --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 69fb648..8585e63 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A **variable font** is a single `.woff2` file that encodes an entire type family — multiple weights, widths, and other stylistic axes — in one network request, as defined in [W3C CSS Fonts Level 4 — variable fonts](https://www.w3.org/TR/css-fonts-4/#font-variation-props). This repository provides a working reference implementation showing how to correctly load a variable font using CSS [`@font-face`](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face), declare full axis ranges (`font-weight: 100 900`, `font-stretch: 75% 125%`), and manipulate axes at runtime using [`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) in JavaScript (`demo/script.js`). It also covers common mistakes — serving fonts without the required `Access-Control-Allow-Origin` CORS headers when HTML and fonts are on different origins ([pc-010](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#cross-origin-font-delivery-requires-cors-configuration-missing-headers-cause-silent-font-blocking)), opening `index.html` via `file://`, and using a desktop license for web delivery ([pc-008](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#self-hosting-web-fonts-requires-a-web-font-license-desktop-licenses-do-not-permit-web-delivery)). -The `demo/` folder is a working reference running entirely in a browser. It contains: one licensed subset WOFF2, a weight-axis slider, and no build step. Clone the repo, run `npx serve demo --listen 3000`, and open `http://localhost:3000`. +The `demo/` folder contains the working reference which runs entirely in a browser. It contains one licensed subset WOFF2, a weight-axis slider, and requires no build step. Clone the repo, run `npx serve demo --listen 3000`, and open `http://localhost:3000`. **Browser support (as of May 2026):** Variable fonts and [`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) are supported in all major browsers — Chrome 62+, Firefox 62+, Safari 11+, Edge 17+ — with global support above 97% ([caniuse: variable fonts](https://caniuse.com/variable-fonts)). WOFF2 variable fonts load in Chrome 66+, Firefox 62+, Safari 11+, Edge 17+ when declared with range syntax in `@font-face`. From ab3860e23d0a09ab9d6b38a7538b9997c3ffeddf Mon Sep 17 00:00:00 2001 From: Jeff Carey Date: Tue, 2 Jun 2026 09:34:19 -0700 Subject: [PATCH 6/6] usually --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8585e63..6af096b 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Omitting the range causes the browser to synthesize bold or ignore axis values o ### Do I need a special license to self-host a variable font? -Yes. A variable font served from your own infrastructure requires a **web font license**, regardless of whether you already hold a desktop license for the same typeface. A desktop license does not permit web delivery. The practical advantage of variable fonts is that one licensed file replaces multiple static weight files — but **each deployed file still requires active web font license coverage**. See [pc-008](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#self-hosting-web-fonts-requires-a-web-font-license-desktop-licenses-do-not-permit-web-delivery). +Yes. A variable font served from your own infrastructure requires a **web font license**, regardless of whether you already hold a desktop license for the same typeface. A desktop license usually does not permit web delivery. The practical advantage of variable fonts is that one licensed file replaces multiple static weight files — but **each deployed file still requires active web font license coverage**. See [pc-008](https://github.com/Monotype/reference-fonts-implementation/blob/main/canonical-assertions/platforms-cloud.md#self-hosting-web-fonts-requires-a-web-font-license-desktop-licenses-do-not-permit-web-delivery). ### Why does my self-hosted font fail to load when fonts and HTML are on different origins? @@ -143,7 +143,7 @@ Not all variable fonts expose both `wght` and `wdth`. Check your font's axis tab ## How to implement a self-hosted variable font from scratch **Step 1 — Obtain a licensed variable font `.woff2` file.** -Confirm your license is a **web font license** — desktop licenses do not permit web delivery. Store the file where your server can serve it (this demo uses `demo/MyVF.woff2`). +Confirm your license is a **web font license** — desktop licenses usually do not permit web delivery. Store the file where your server can serve it (this demo uses `demo/MyVF.woff2`). ```bash # Place your licensed variable font in the demo directory