Text✨ Premium

Scroll Weight

Typographic weight animated from 100 to 900 by the native browser scroll — animation-timeline: scroll(), zero JavaScript.

CSSScrollWeight

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

Agency landing — A single word gaining weight as you scroll — Scroll Weight example 1

① Agency landing — A single word gaining weight as you scroll

WhenOn the hero section of an agency, portfolio, or product launch site, where the visitor naturally scrolls to discover the content.
WhyA single word at large scale reveals the full weight range of a variable font through scroll — immersive, no JavaScript, entirely under the user's control.
Settingsfont-size: 6rem, variable font recommended (system-ui, Inter Variable), container height: 500px, content height: 1200px to spread the animation across the full hero section.
In-depth article — Chapter title that anchors and asserts itself while reading — Scroll Weight example 2

② In-depth article — Chapter title that anchors and asserts itself while reading

WhenIn a longread or magazine article, the current section title stays sticky and gains weight as the reader progresses through the content.
WhyTypography growing heavier as you read is a visual metaphor for the weight given to the content — strong editorial identity, zero JS.
Settingsfont-size: 2.5rem, letter-spacing narrowed to 4px → 0px for multi-word titles, editorial color (#e2e8f0).
Brand manifesto — A keyword that grows heavier as you read — Scroll Weight example 3

③ Brand manifesto — A keyword that grows heavier as you read

WhenOn a manifesto page, an About page, or a brand statement, where a central term (TRUST, BOLD, IMPACT…) is anchored in large format while the supporting argument scrolls beneath it.
WhyThe word literally embodies its meaning: the further the reader absorbs the argument, the heavier the term reads visually — no JavaScript, 100% CSS scroll-driven, and deeply memorable.
Settingsfont-size: 5–8rem, variable font recommended, position: sticky; top: 50% on .vf-scroll-text, container height: 300px and content height: 960px for an ample scroll range; initial letter-spacing: 10px for wide-set large type.

How it works

animation-timeline: scroll() (CSS Scroll-driven Animations, Level 1) binds a @keyframes animation's progress to a scroll container's scroll position, with no requestAnimationFrame or JavaScript event. On .vf-scroll-text, the declaration automatically targets the nearest ancestor marked as a scroll container — here .vf-scroll-container (overflow-y: auto). The browser maps the scroll position (0% at top, 100% at bottom) to the animation state on the compositor thread, off the main thread.

The vfScrollWeight animation is a symmetric round-trip in three steps: at 0% (no scroll), font-weight: 100, letter-spacing: 8px, opacity: 0.4; at 50% (mid-scroll), font-weight: 900, letter-spacing: -2px, opacity: 1; at 100% (end), back to the initial state. The weight rises then falls symmetrically — interpolation between 100 and 900 is smooth with a variable font covering the full weight axis.

The text is sticky-positioned at the vertical center of .vf-scroll-container — it stays visible throughout the scroll despite .vf-scroll-content being 800 px tall. The effective scroll range (800 − 280 = 520 px) determines the amplitude and perceived "duration" of the transformation.

If animation-timeline is not supported, font-weight stays frozen at 100 — text is readable but static. No JavaScript error is thrown since the effect is entirely CSS.

Accessibility

  • prefers-reduced-motion: absent from the code. No @media (prefers-reduced-motion: reduce) rule is defined — the animation stays active even when the OS requests reduced motion. Add it if needed: @media (prefers-reduced-motion: reduce) { .vf-scroll-text { animation: none; font-weight: 400; } }.
  • No ARIA attributes in the provided structure — neither role nor aria-label on the container. Add them if the scene is the sole semantic content of a section.
  • Contrast: white text (#fff) on #0a0a0f exceeds a 18:1 ratio — including at opacity: 0.4 (effective ratio ~7:1), well above the WCAG AA threshold (4.5:1).
  • Text legibility is maintained at every weight: even at font-weight: 100, the word remains perceptible on a dark background.
  • No interactive elements are introduced — no keyboard interaction or focus management required for the effect itself.

Browser compatibility

Requires animation-timeline: scroll() (CSS Scroll-driven Animations, Level 1). No JavaScript dependency.

Chrome 115+✓ Full
Firefox 114+✓ Full
Safari 17.2+✓ Full
Edge 115+✓ Full
Mobile iOS 17.2+✓ Full
Android Chrome✓ Full

On Safari < 17.2 and Firefox < 114, <code>font-weight</code> stays frozen at <code>100</code> — text is visible but static. No JS error (100% CSS effect).

The code

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

index.html — structure
<div class="vf-preview">
  <div class="vf-scroll-container">
    <div class="vf-scroll-content">
      <span class="vf-scroll-text">YOUR TEXT</span>
    </div>
  </div>
  <span class="vf-scroll-hint">Scroll ↓</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-size on .vf-scroll-text 3rem Size of the animated text. Large for a hero (5–8 rem), small for a component integration (1–1.5 rem).
font-family on .vf-scroll-text Inter, sans-serif Font. Must cover weights 100–900 for smooth interpolation — variable font recommended (Inter Variable, DM Sans, Plus Jakarta Sans, system-ui).
color on .vf-scroll-text #fff Text color. Adjust to your palette — contrast is maintained on dark backgrounds at every weight.
font-weight at 0% and 100% in @keyframes vfScrollWeight 100 Starting weight (no scroll) and ending weight (full scroll). Raise to 300 for a less extreme start.
font-weight at 50% in @keyframes vfScrollWeight 900 Peak weight at mid-scroll. 700 = classic Bold, 900 = Black — depends on your variable font's available axes.
letter-spacing in @keyframes vfScrollWeight 8px → -2px Starting and ending letter spacing. Narrow to 2px → 0px for multi-word titles legible at all stages.
height on .vf-scroll-container 280px Height of the visible scroll area. Increase for a hero section, decrease for a compact component.
height on .vf-scroll-content 800px Total height of the scrollable content. The effective range (800 − 280 = 520 px) determines the scroll effort needed to traverse the animation. Decrease to 400px for a faster trigger.

FAQ

Yes, since Safari 17.2 (December 2023) and Firefox 114 (June 2023). On older versions, the text stays static at font-weight: 100 — readable but unanimated. No JavaScript error is thrown because the effect is 100% CSS.
Replace animation-timeline: scroll() with animation-timeline: scroll(root) on .vf-scroll-text, and remove overflow-y: auto from the container. The text will then animate based on the global page scroll — no oversized .vf-scroll-content needed.
No, but it is strongly recommended. With a non-variable font, the browser interpolates only between available weights (e.g. Normal 400 and Bold 700) — the transition is visible but in two or three discrete jumps. A variable font with the wght axis 100–900 gives continuous, pixel-perfect interpolation.