AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Variable Fonts

skill-jpoindexter-typography-skills-variable-fonts · by jpoindexter

Use when working with variable fonts — choosing between variable and static files, using weight/width/optical-size/slant axes, setting font-variation-settings vs standard properties, animating axes, or deciding whether a variable font actually saves bytes. Also use when a variable font renders wrong or ignores its axes.

No reviews yet
0 installs
24 views
0.0% view→install

Install

$ agentstack add skill-jpoindexter-typography-skills-variable-fonts

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-jpoindexter-typography-skills-variable-fonts)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Variable Fonts? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Variable fonts

One file containing a continuous design space instead of discrete instances. Powerful and frequently misused — the most common error is reaching for font-variation-settings when a standard CSS property already maps to the axis.

1. When to invoke

  • Choosing between a variable font and a set of statics.
  • Using weight, width, optical size, slant, or italic axes.
  • Axes not responding, or rendering incorrectly.
  • Animating or transitioning a typographic axis.
  • Auditing whether a variable font is actually paying for itself.

2. Required context

  • Which axes the font exposes, and their ranges (read the font, don't

assume — wght 100–900 is common but not universal).

  • How many instances you'd otherwise ship.
  • Real byte comparison: variable file vs. the statics it replaces.
  • Whether you need continuous values or only named instances.
  • Whether the design needs optical sizing.

3. Invariant principles

  • **Use standard CSS properties, not font-variation-settings, wherever one

exists.** Registered axes map to real properties:

| Axis | Standard property | |---|---| | wght | font-weight | | wdth | font-stretch (or font-width) | | opsz | font-optical-sizing | | ital | font-style: italic | | slnt | font-style: oblique |

font-variation-settings is a low-level override. It does not inherit predictably per-axis — setting it replaces the whole list, so a child that sets one axis loses every other. It also bypasses the cascade's understanding of weight, breaking things like font-synthesis control and browser bolding logic. Reserve it for custom (unregistered) axes only.

  • Declare the axis range in @font-face. font-weight: 100 900 on the

@font-face rule tells the browser the file covers that span; omit it and the browser may treat the font as a single weight and synthesize faux bold.

  • A variable font is not automatically smaller. It carries the whole design

space. Compare real bytes.

  • Only ship the axes you use. Instancing/subsetting can strip unused axes.

4. Context-dependent heuristics

Variable vs. static — the break-even.

| Instances needed | Usually | |---|---| | 1–2 | Static wins | | 3 | Roughly even — measure | | 4+ | Variable usually wins | | Continuous values or animation | Variable, necessarily |

Measure, don't assume. A variable file replacing two weights often costs bytes.

Optical size (opsz) is the underused one. It adjusts the design for the size it's rendered at — more contrast and tighter spacing at display sizes, sturdier forms and looser spacing at text sizes. This is what metal type did by cutting each size separately. Enable with font-optical-sizing: auto (browsers apply it from font-size automatically when the axis exists). Turn it off only deliberately.

Weight is now continuous. You can use 450 or 530. Resist it in a design system — the value of a scale is exclusion. Pick your named steps and tokenize them.

Grade (GRAD) — the axis most people don't know they need. Grade changes apparent weight without changing advance widths, so text gets visually heavier or lighter while occupying exactly the same space. Nothing reflows.

Two uses:

  • Dark mode. Light-on-dark text appears optically bloated — the light strokes

bleed into the dark ground. Drop the grade slightly in dark mode and the text reads at the same visual weight as its light-mode counterpart. (In print the relationship inverts.) This is the correct fix for "our dark mode looks heavier", far better than switching to a lighter weight, which would reflow the line.

  • Interaction states. Because nothing reflows, grade is safe for hover and

active states in a way font-weight is not.

GRAD is a custom axis (Roboto Flex exposes it), so it is one of the legitimate cases for font-variation-settings — there is no standard property for it.

Parametric axes go further still, exposing thin-stroke, thick-stroke, counter width, and similar low-level parameters. Powerful for fine-tuning a face to a specific context; easy to produce something the type designer would not recognise. Use sparingly and compare against the designed instances. Custom axes are arbitrary — a type designer can expose almost any parameter of the design this way, down to contrast, x-height, serif shape, or the length of a single glyph's tail (Rutter cites a Q's tail as a real example); the four-character tag is whatever the foundry chose, so read the specimen rather than guessing at what a custom axis controls.

Multiplexed fonts solve the same reflow problem a different way: every weight occupies identical horizontal space by design, so switching weight never changes width. See ui-component-typography.

Animation. Axes are animatable, which enables genuinely new effects. Constrain it: animating wght reflows text if the width changes, and any motion must respect prefers-reduced-motion.

@media (prefers-reduced-motion: no-preference) {
  .headline { transition: font-variation-settings 200ms ease; }
}

Fallbacks. Variable font support is universal in current browsers, but the file still has to load. The metric-matched-fallback technique in font-loading-and-performance applies unchanged.

5. Failure patterns

| Pattern | Cause | Fix | |---|---|---| | Faux bold despite a variable font | @font-face didn't declare the range | font-weight: 100 900 in @font-face | | Child element loses width/optical settings | font-variation-settings replaces the whole list | Use standard properties | | Variable font larger than the statics it replaced | Replaced too few instances | Measure; consider statics | | Axis has no effect | Axis not present, or outside its range | Inspect the font's actual axes | | Text reflows during a weight animation | Weight change alters advance widths | Animate a non-reflowing property, or reserve space | | Display text looks flabby at 72px | opsz unused or disabled | font-optical-sizing: auto | | Design drifts to arbitrary weights | Continuous axis, no tokens | Tokenize named steps | | Dark mode text looks heavier than light mode | Optical bloat of light-on-dark | Lower GRAD, not wght — no reflow | | Hover state shifts the layout | font-weight changes advance widths | GRAD, or a multiplexed face | | Parametric tuning produced something odd | Low-level axes pushed past the design space | Compare against the designed instances | | Motion sickness complaints | Axis animation, no reduced-motion guard | Wrap in the media query |

6. Evaluation procedure

  1. Inspect the font's actual axes and ranges (browser devtools, fonttools, or

the foundry spec). Don't assume.

  1. Count the instances the design genuinely uses.
  2. Measure both: variable file vs. sum of the statics, after subsetting.
  3. Confirm @font-face declares each axis range.
  4. Confirm standard properties are used for registered axes; font-variation-settings

only for custom axes.

  1. Check inheritance: set an axis on a parent, verify a child that changes one axis

retains the rest.

  1. If opsz exists, verify font-optical-sizing: auto and compare display vs. text

rendering.

  1. Confirm no faux bold/italic is being synthesized.
  2. If animating, verify prefers-reduced-motion is respected and no reflow occurs.

7. Output format

Font: 
Axes available: 
Axes used:  — via 
@font-face ranges declared: 
Instances replaced:  — variable KB vs statics KB → 
Optical sizing:  — because 
Tokenized weights: 
Faux synthesis: 
Reduced-motion respected: 

8. Examples

Design system shipping Inter at 400/500/600/700 as four static files.

> Four instances is past the break-even, and the variable file measures smaller > than the four statics after subsetting, so switch. Declare > font-weight: 100 900 in @font-face so the browser knows the span and stops > synthesizing. Use font-weight — not font-variation-settings — so the cascade > and font-synthesis keep working. Tokenize exactly the four existing steps > despite the axis now being continuous; the scale's value is that 530 is > unavailable.

Headline set in a family with an opsz axis, looking weak at 64px.

> The optical size axis isn't engaged, so the display setting is using text-optimised > forms — too little contrast and too much spacing for 64px. font-optical-sizing: > auto lets the browser drive opsz from the rendered size; the headline picks up > the higher-contrast, tighter-spaced cut it was designed to have. No markup change, > no extra bytes.

9. Counterexamples

  • font-variation-settings: "wght" 700 when font-weight: 700 exists. — Breaks

inheritance and cascade behavior.

  • ❌ "Variable fonts are always smaller." — They carry the full design space; two

weights are often cheaper as statics.

  • ❌ Omitting font-weight: 100 900 from @font-face. — Invites faux bold.
  • ❌ "We have a continuous weight axis, so let designers pick any value." — Destroys

the system's constraint.

  • ❌ Animating wght on body text without checking reflow or reduced-motion.
  • ❌ "It has an opsz axis so it handles sizes automatically." — Only if optical

sizing is enabled and not overridden.

10. Source citations

  • Current standards take precedence here — variable fonts postdate most of the

corpus. MDN — variable fonts guide, font-variation-settings, font-optical-sizing. web.dev — optimize web fonts.

  • Stocks, Universal Principles of Typography (2024) — the most current book in the

corpus on variable fonts. §29 multiple widths; §30 masters and interpolation (weight and width masters combined by vector addition); §31 multiplexed typefaces; §84–85 variable fonts and axes; §86 grade — "grade, unlike weight (except in multiplexed fonts), doesn't affect the overall width of the glyphs", and "on screens, light-on-dark text will appear slightly bloated, so, if possible, switch to a lighter grade when designing for Dark Mode. The opposite is true in print"; §87 parametric axes; §88 the inheritance problem; §27 avoid faux styles.

  • Brown, Flexible Typesetting — designing typographic systems that adapt rather

than fixed instances; the conceptual case for continuous ranges.

  • Rutter, Web Typography — OpenType foundations that variable fonts extend;

custom axes as arbitrary designer-defined parameters (contrast, x-height, serif shape, individual glyph details) reachable only through font-variation-settings. His browser-support and format-string details (format('woff-variations'), multiple repeated @font-face rules for fallback, an early-2018 viability estimate) are from 2017 and superseded — variable font support is now universal; don't carry those specifics forward.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.