Text✨ Premium

Variable Font Weight

Pure CSS animation that smoothly slides a variable font's weight from 400 to 900 on hover — no script, a single element.

CSSHoverVariable Font

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

Typographic poster — Words that gain volume — Variable Font Weight example 1

① Typographic poster — Words that gain volume

WhenOn a portfolio page, design studio, or artistic landing page where typography is the primary visual element.
WhyAt large sizes (5–8 rem), the continuous slide from 400 to 900 creates a perceptual depth with no image — each hovered word becomes the animation.
Settingsfont-weight from 200 to 900, transition: font-weight .5s ease, font-size: 7rem, letter-spacing: -0.05em.
Minimal navigation — Links that assert themselves on hover — Variable Font Weight example 2

② Minimal navigation — Links that assert themselves on hover

WhenIn a clean navigation bar where the active state should stay subtle — no underline, no color change, only weight.
WhyThe weight shift replaces underlines or tint changes while staying within the same typographic token — the effect reads as natural at 0.2 s in a UI context.
Settingsfont-weight from 400 to 700, transition: font-weight .2s, font-size: 1rem.
Key metric in data viz — A score that intensifies — Variable Font Weight example 3

③ Key metric in data viz — A score that intensifies

WhenOn a presentation slide or dashboard where a strong indicator (NPS, conversion rate, growth) must register at a glance — hovering reveals its full visual weight.
WhyThe 100→900 weight glide encodes the value's intensity: a large ultralight number that becomes ultrabold on hover conveys impact without color or counter animation.
Settingsfont-weight from 100 to 900, transition: font-weight .5s ease-in-out, font-size: 6rem.

How it works

The effect is entirely CSS-driven: the element's font-weight transitions from 400 to 900 on hover via a :hover rule, and the declaration transition: font-weight .3s interpolates that value continuously over 300 ms. The interpolation is smooth only when the loaded font is a variable font that supports the wght axis — Inter, specified here, covers values 100 to 900 without gaps.

On a static font or a system where Inter is not available, the browser substitutes sans-serif and the transition snaps to the nearest available weight with no smooth glide. The effect remains functional but loses its animation. No JavaScript is loaded or executed — the JS field in the code file is an empty string; the effect is 100% stylesheet.

Accessibility

  • prefers-reduced-motion: not in the code. The transition runs regardless of the OS setting — for accessibility, add @media (prefers-reduced-motion: reduce) { .text-variable-weight { transition: none } }.
  • The text element (<span>) is a pure text node, fully readable by screen readers — no aria attributes are needed for this decorative effect.
  • The effect is triggered by :hover only; no :focus-visible state is defined. On an interactive link or button, add a keyboard equivalent.
  • On touch devices, :hover does not fire on a simple tap — the animation stays invisible without a pointer device.
  • Text/background contrast depends entirely on the integration context — the effect defines neither text color nor background color.

Browser compatibility

Smooth weight interpolation requires a variable font with the wght axis and a browser supporting CSS transitions on font-weight.

Chrome 88+✓ Full
Firefox 63+✓ Full
Safari 14+✓ Full
Edge 88+✓ Full
Mobile iOS 14+✓ No hover
Android Chrome✓ No hover

If Inter is not available as a variable font, the transition snaps to the target weight without interpolation — no JS error, text stays readable.

The code

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

index.html — structure
<div class="demo-preview">
  <span class="demo-text text-variable-weight">Your text</span>
</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-weight (normal state) 400 Resting weight — use 100–300 for maximum contrast with the target.
font-weight (:hover state) 900 Target weight on hover — any integer the variable font supports (100–900).
transition: font-weight .3s .3s ease Animation duration and easing — .15s for a snappy pop, .6s ease-in-out for a cinematic glide.
font-family Inter, sans-serif Font in use — must be a variable font with a wght axis (Inter, Roboto Flex, Manrope, Source Sans 3…).
font-size 2.5rem (inherited from .demo-text) Text size — the effect is more visible at larger sizes.
letter-spacing -.02em (inherited from .demo-text) Tracking — adjust if the weight change shifts the text's optical rhythm.

FAQ

Only with a variable font that exposes the wght axis. On a static font, the browser picks the nearest available weight and the transition snaps without a smooth glide. Inter loaded from Google Fonts (or installed as a system font) is variable and will interpolate correctly.
Yes — change the values in .text-variable-weight { font-weight: 400 } and .text-variable-weight:hover { font-weight: 900 }. Any integer pair is valid as long as the variable font supports those values. Examples: 100 → 800 for a dramatic effect, 400 → 600 for a UI-friendly subtlety.
Wrap each word in its own <span class="text-variable-weight">. Each span is self-contained — the :hover state is individual and no JS initialization is required.