Text✨ Premium

Optical Size

Fraunces' opsz axis adapts typographic details by size — serifs, contrast, letter-spacing — from 9 to 144, in pure CSS.

CSSopszTypography

You'll get access to the interactive demo with a free account.

This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Text has 56 effects, including 4 free. Explore the category →

3 usage examples

Digital magazine — Masthead and article deck — Optical Size example 1

① Digital magazine — Masthead and article deck

WhenAn article page or online publication placing a large display headline, a subheading deck, and a few body lines in the same type family.
WhyShowing opsz 144 (headline), opsz 48 (deck), and opsz 9 (body) together makes it clear without explanation why the display cut is too aggressive at small sizes — and vice versa.
Settingsopsz 144 / wght 700 for the headline (2rem), opsz 48 / wght 500 for the deck (1rem), opsz 9 / wght 400 for body copy (0.75rem). Thin horizontal rule between tiers.
Design system — Variable font type specimen — Optical Size example 2

② Design system — Variable font type specimen

WhenA design system documentation page or Storybook documenting the typographic hierarchy and font axes for the team's developers and designers.
WhyThe <code>.vf-opsz-tag</code> labels display the active opsz value for each tier — a plug-and-play pedagogical demo that can be copied directly into design token docs.
SettingsDefault 3-tier structure (opsz 144 / 48 / 9) wrapped in a card with a subtle border. Adapt the copy to the target design system's heading hierarchy.
SaaS landing page — Display headline and intro paragraph — Optical Size example 3

③ SaaS landing page — Display headline and intro paragraph

WhenA landing page hero where a display headline (> 40px) and an intro paragraph (16–18px) coexist in the same type family on a dark background.
WhyOne variable font file covers both display and body copy — one network request, two optically optimised designs. The benefit is both network performance and visual consistency.
Settingsopsz 144 for the headline (2rem, wght 800 possible), opsz 9 for body (0.85rem, wght 300 for lightness). The wght axis can vary independently of opsz with no extra network cost.

How it works

The effect relies on the CSS property font-variation-settings, which exposes variable font axes. The standardised "opsz" axis (optical size) produces two distinct designs: a low value generates a text cut (open strokes, wide serifs, reduced contrast); a high value generates a display cut (sharp serifs, high stroke contrast, tighter letter-spacing). No JavaScript, no images — one CSS rule per size level is enough.

Fraunces is a variable serif font with an opsz axis from 9 to 144 and a wght axis from 100 to 900. At opsz 144 / wght 700, serifs are fine and high-contrast, designed for display headlines. At opsz 9 / wght 400, strokes open up and serifs widen to stay legible at small sizes. opsz 48 is a natural intermediate level for subheadings.

Three CSS classes each apply a specific pair of values. .vf-opsz-large sets font-variation-settings: "opsz" 144, "wght" 700 at 2rem. .vf-opsz-medium sets "opsz" 48, "wght" 500 at 1rem. .vf-opsz-small sets "opsz" 9, "wght" 400 at 0.75rem. All three are stacked in .vf-opsz-scene (flex-column, gap: 20px, horizontally centred). Side by side, they reveal that the opsz axis is an adaptive redesign of letterforms, not a simple zoom.

The .vf-opsz-tag labels use Recursive with font-variation-settings: "MONO" 1 — the font switches to a monospace render without changing family. They display the active opsz value for each tier and carry a semi-transparent violet badge (rgba(139,92,246,.15)) to stay subtle while informative.

Accessibility

  • No animation: the effect is entirely static (pure CSS, zero requestAnimationFrame). prefers-reduced-motion is not applicable — there is no motion to reduce.
  • Main text contrast: white (#ffffff) on black (#0a0a0f) — ratio ≥ 7:1, WCAG AAA. The .vf-opsz-small text at rgba(255,255,255,.5) reaches ~4.6:1 AA at the rendered size (≥ 12px).
  • The <span class="vf-opsz-tag"> elements are read by screen readers (e.g. "opsz 144"). If purely decorative, add aria-hidden="true" to each span.
  • No interactive elements in the base structure — no tab focus required. No focus trap introduced if a parent component is clickable.
  • Typographic fallback: font-family: Fraunces, serif — if the variable font is not loaded, text stays readable in the system serif with no JS error or visual crash.

Browser compatibility

Requires CSS font-variation-settings (variable fonts) — supported in all modern browsers since 2018. Zero JS dependencies.

Chrome 66+✓ Full
Firefox 62+✓ Full
Safari 11+✓ Full
Edge 79+✓ Full
Mobile iOS 11+✓ Full
Android Chrome✓ Full

If Fraunces is not loaded, the browser falls back to the system <code>serif</code> — text stays readable but the opsz axis demonstration is lost. Loading Fraunces from Google Fonts (<code>opsz,wght@9..144,100..900</code>) guarantees the expected render.

The code

HTML structure to paste into your page (CSS + JS available with a premium account):

index.html — structure
<div class="vf-opsz-scene">
  <div class="vf-opsz-row">
    <div class="vf-opsz-large">Display headline
      <span class="vf-opsz-tag">opsz 144</span>
    </div>
  </div>
  <div class="vf-opsz-row">
    <div class="vf-opsz-medium">Subheading
      <span class="vf-opsz-tag">opsz 48</span>
    </div>
  </div>
  <div class="vf-opsz-row">
    <div class="vf-opsz-small">Body copy — adapted for comfortable reading
      <span class="vf-opsz-tag">opsz 9</span>
    </div>
  </div>
</div>
🔒 Unlock the full code — from €2.99 the first month

Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
font-variation-settings: "opsz" 144 144 Display value in .vf-opsz-large — valid Fraunces range: 9–144. Lower to 72 for a softer display.
font-variation-settings: "opsz" 48 48 Mid-level value in .vf-opsz-medium — lower to 24–30 for an h3 or a caption.
font-variation-settings: "opsz" 9 9 Body value in .vf-opsz-small — optimised for ≈ 12px. Raise to 14 for 16–18px body copy.
font-variation-settings: "wght" (per level) 700 / 500 / 400 Independent weight per tier, freely adjustable without affecting opsz. E.g. wght 900 for a very bold display.
font-size (.vf-opsz-large) 2rem CSS size of the display tier — increase to 3–4rem for a full-screen hero. Fraunces scales to very large sizes without quality loss.
font-family: Fraunces, serif Fraunces Replace with any variable font exposing an opsz axis (Literata, Newsreader, Source Serif 4…). The axis range varies by font.
gap (.vf-opsz-scene) 20px Vertical spacing between the 3 typographic tiers in the flex-column container.

FAQ

Yes. The effect relies on Fraunces, a Google Fonts variable font with an opsz axis (9–144) and a wght axis (100–900). Load it via: <link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,100..900&display=swap" rel="stylesheet">. The labels use Recursive (MONO axis) — omit them if you don't need the badges.
A real redesign. The opsz axis changes the actual glyph coordinates: at opsz 9, serifs widen, thin strokes open up, and contrast decreases to compensate for the optical effect of small sizes. At opsz 144, serifs sharpen and contrast increases for display impact. This is not a CSS scale transform — the letterforms genuinely change.
font-variation-settings is animatable in CSS (transition: font-variation-settings 0.4s ease) and JavaScript (el.style.fontVariationSettings = '"opsz" 72, "wght" 600'). The browser interpolates axis values frame by frame — useful for a hover that slides a heading from opsz 48 to opsz 144.