Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
FontFace API

Variable Fonts in HTML5 Canvas: Loading, Drawing, and Handling Variation Axes

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To draw a variable font in HTML5 Canvas, load it with the CSS Font Loading API, wait for FontFace.load(), add the loaded face to document.fonts, set ctx.font with CSS font shorthand, and only then call a text-drawing method. A variable font can contain several design axes in one file, but the file—not Canvas—defines which axes and value ranges actually exist.

The reliable Canvas workflow

Canvas does not automatically wait for a web font before painting. If you draw while the font is still unavailable, the browser can use a fallback face and your text may have different widths, line breaks, and visual weight. Use this sequence:

  1. Create a FontFace with a family name and the font URL.
  2. Call load() and await the returned promise.
  3. Add the resolved face to document.fonts.
  4. Obtain the 2D context and assign ctx.font.
  5. Draw text only after those steps complete.

The default Canvas font is 10px sans-serif. The value assigned to ctx.font uses CSS font shorthand, so include a size and a family, such as 600 32px "Example Variable", sans-serif.

Complete HTML and JavaScript example

Place a variable-font file at /fonts/example-variable.woff2. This example waits for the font, scales the backing store for a crisp result, and then draws text.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Variable font on Canvas</title>
<canvas id="art" width="800" height="180"></canvas>
<script type="module">
  const face = new FontFace(
    "Example Variable",
    'url("/fonts/example-variable.woff2")'
  );

  async function draw() {
    try {
      await face.load();
      document.fonts.add(face);

      const canvas = document.querySelector("#art");
      const ratio = window.devicePixelRatio || 1;
      const cssWidth = 800;
      const cssHeight = 180;
      canvas.width = cssWidth * ratio;
      canvas.height = cssHeight * ratio;
      canvas.style.width = `${cssWidth}px`;
      canvas.style.height = `${cssHeight}px`;

      const ctx = canvas.getContext("2d");
      ctx.scale(ratio, ratio);
      ctx.clearRect(0, 0, cssWidth, cssHeight);
      ctx.font = '600 32px "Example Variable", sans-serif';
      ctx.fillStyle = "#111827";
      ctx.fillText("Variable font", 20, 70);
    } catch (error) {
      console.error("Font could not be loaded; using fallback text.", error);
    }
  }

  draw();
</script>
</html>

The try/catch prevents a network or decoding failure from stopping the rest of the page. In a production application, decide whether a fallback rendering is acceptable or whether you should report the failure and avoid exporting an image with the wrong metrics.

What “variable” means

A variable font packages a range of designs in one font file. Common registered axes include weight (wght), width (wdth), italic (ital), slant (slnt), and optical sizing (opsz). A particular file may omit any of these and may add custom axes. Always inspect the font documentation or metadata for the exact tags, minimums, maximums, and defaults.

Axis tags are four ASCII characters and are case-sensitive. Registered tags are conventionally lowercase; custom tags are conventionally uppercase. A value outside the font’s declared range is not a portable way to request a design, so clamp values to the range supplied by the foundry.

Choosing an axis control

Design need Preferred control Canvas qualification
Weight CSS font-weight expressed in the ctx.font shorthand Use a value supported by the font; the file determines the useful range.
Width CSS font-stretch or the Canvas fontStretch property where supported The documented Canvas property uses keyword values; its documentation does not support percentage values. Do not treat it as arbitrary numeric wdth control.
Italic or oblique CSS font-style in the font shorthand Use the style that the font exposes; an ital axis is not guaranteed.
Optical size or a custom axis CSS font-variation-settings when rendering CSS text The reviewed Canvas interfaces do not establish a portable, direct arbitrary-axis property on a 2D context. Test every target browser and font before depending on one.

For standard axes, prefer the high-level property because it communicates intent and lets the browser apply the registered axis semantics. CSS’s font-variation-settings is the low-level mechanism for custom axes or cases where no suitable high-level property exists, but that CSS declaration controls CSS text. It does not, by itself, prove that a Canvas context accepts the same arbitrary axis settings.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Do not build production code around ctx.fontVariationSettings as though it were a universally available Canvas API. The documented Canvas context exposes separate font controls, including fontStretch, while cross-browser arbitrary-axis behavior is not established by the references used here. If custom-axis control is essential, keep a browser test matrix or render that text outside Canvas.

Using registered properties in a Canvas font string

Registered weight and style values can be put directly in the CSS shorthand:

ctx.font = '750 28px "Example Variable", sans-serif';
ctx.fillText("Heavy text", 20, 45);

ctx.font = 'italic 28px "Example Variable", sans-serif';
ctx.fillText("Italic text", 20, 90);

Whether a numeric weight or italic style produces a continuous variation depends on the font’s own axis definitions. A static-looking result can simply mean that the file has a limited range or no matching axis.

CSS feature detection around Canvas

When the same variable font is used for ordinary HTML text, a feature query can gate CSS variation settings:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
@supports (font-variation-settings: "wdth" 115) {
  .condensed-label {
    font-variation-settings: "wdth" 115;
  }
}

This tells you whether the browser accepts that CSS declaration. It does not establish arbitrary-axis support through Canvas. Keep Canvas compatibility decisions separate and verify the exact browser, operating-system font stack, and file you ship.

Font loading, caching, and redraw behavior

Load once and reuse the face

Create and load a FontFace once per family and retain it when drawing many frames or canvases. Repeatedly constructing faces adds needless work and can make timing harder to reason about. The browser may cache the underlying resource, but your code should still await the face before the first draw.

Redraw after a late load

If your application initially paints a fallback and later receives the variable font, redraw the canvas after the face is added. Canvas pixels do not automatically change when a font finishes loading. Recompute measured widths, wrapping, alignment, and any hit-test coordinates during that redraw.

Handle a failed load explicitly

Common causes include a wrong URL, a server response that is not a font, a blocked cross-origin request, an unsupported format, or a corrupted file. Log the error, show a known fallback, and avoid silently exporting a result whose typography does not match the design.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Text measurement and layout details

Set ctx.font before calling measureText(); measurements belong to the current font state. If you change weight, style, size, or family, measure again. Variable-axis changes can alter advance widths and therefore line wrapping, centering, clipping, and collision calculations. For deterministic output, keep the font-loading promise in the same initialization path that creates the canvas scene.

Canvas text is drawn at a baseline. Use textBaseline, textAlign, and explicit coordinates rather than assuming that changing a font axis leaves the visual bounds unchanged. For multi-line text, calculate each line after the final font state is selected.

Performance and reliability checklist

  • Prefer WOFF2 when your supported browsers and licensing permit it, and serve it with a correct font media type.
  • Load the face before starting an animation or export job so a fallback frame is not captured as the final output.
  • Reuse a loaded face and avoid changing font state for every glyph when batching is possible.
  • Measure only after setting the exact font string used for drawing.
  • Use a device-pixel-ratio scale for sharp output, but remember that larger backing stores consume more memory and drawing time.
  • Test slow-network, offline, blocked-font, and corrupted-file paths; a successful local development load does not cover them.
  • Verify glyph coverage. A variable font can load successfully while particular characters still fall back to another font.
  • Record the browser and font version in visual-regression tests because browser support and Baseline labels can change.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting common failures

The text looks like a system font

Confirm that await face.load() completed, that document.fonts.add(face) ran, and that the family name in ctx.font exactly matches the name passed to FontFace. Check the network panel for a 200 response and verify that the response is the intended font file.

Changing wght has no visible effect

The file may not contain a weight axis, the requested value may be outside its range, or the browser may be using a fallback glyph. Check the font’s axis metadata and test with a clearly different registered weight before investigating Canvas behavior.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
HTML5 Canvas
  • Used Book in Good Condition

Width percentages do not work with fontStretch

The documented Canvas fontStretch control uses keyword values and does not support percentage values. Use a supported keyword where it expresses the design, or treat arbitrary numeric width as a compatibility-sensitive requirement rather than assuming it is available.

The first export has different line breaks

The export probably ran before the font promise resolved. Gate export behind the same initialization promise used for drawing, then clear and redraw the canvas before serializing it.

Only some characters look wrong

Loading succeeded, but the requested glyphs may not be present. Check the font’s language and Unicode coverage and provide an intentional fallback stack in the font shorthand.

A CSS test passes but Canvas still cannot vary an axis

@supports tests CSS parsing, not a direct arbitrary-axis Canvas API. Keep the CSS and Canvas tests separate and use a real rendering test for each browser you support.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Or skip the browser setup

If your goal is to capture a page that already renders variable-font text, ScreenshotNeo can return a screenshot or PDF from one request. It accepts the consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

Use the API documentation at https://screenshotneo.com/docs/ for the complete option list, including full-page capture, lazy-image loading, CSS-selector element capture, dark mode, device presets, custom viewports, retina scale, PDF paper and margin controls, custom CSS and JavaScript, click and wait actions, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL-based caching, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage data, and the OpenAPI specification. Parameter names used by other screenshot APIs are accepted to ease migration.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The Free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots, and yearly billing gives two months free. Create a free ScreenshotNeo account to try the capture without adding a card.

The Bottom Line

Load the variable font with FontFace, await it, add it to document.fonts, set ctx.font, and draw afterward. Use high-level registered font properties when possible; treat arbitrary custom-axis control on Canvas as browser- and font-dependent until your own tests prove otherwise.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Quick Recap

Bestseller No. 1
SaleBestseller No. 3
Bestseller No. 5
HTML5 Canvas
HTML5 Canvas
Used Book in Good Condition
$78.00

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.