scrollvars / fx
docs · demo · bench · llms.txt

Staggered reveal

Children rise in sequence when the section enters the viewport.

Use it for: Heroes, editorial sections, any "content arrives" moment.
Knobs: --sv-distance (travel), --sv-stagger (delay step), --sv-duration, --sv-ease

The headline

Rises second.

Rises third.

<section data-sv data-sv-once class="py-24">
  <h2 class="sv-rise text-4xl font-bold">Title</h2>
  <p class="sv-rise [--sv-order:1]">Copy</p>
  <p class="sv-rise [--sv-order:2] [--sv-distance:3rem]">More</p>
</section>
<!-- once: import 'scrollvars/styles/core.css' + <ScrollVarsBoot /> in the layout -->
<!-- arbitrary classes are for static one-offs. Mapped content: use
     style={{'--sv-order': i}} (the JIT can't see dynamic class names).
     Sequential lists: add sv-stagger to the parent, drop per-child order. -->
<section data-sv>            <!-- tracked; gets .sv-live in the band -->
  <h2 class="sv-rise">Title</h2>
  <p class="sv-rise" style="--sv-order: 1">Copy</p>
</section>

/* needs styles/core.css (or paste the preset): */
.sv-on .sv .sv-rise { opacity: 0; translate: 0 var(--sv-distance, 6rem);
  transition: opacity .8s var(--sv-ease), translate .8s var(--sv-ease);
  transition-delay: calc(var(--sv-order, 0) * var(--sv-stagger, 90ms)); }
.sv-on .sv.sv-live .sv-rise { opacity: 1; translate: 0 0; }
<Reveal auto>            {/* every direct child, stagger for free */}
  <h2>Title</h2>
  <p>Copy</p>
</Reveal>

// or per-child knobs as props:
<Reveal stagger={140}>
  <Item order={0}>first</Item>
  <Item order={1} effect="slide-l" distance="4rem">second</Item>
</Reveal>

Engine: npm i scrollvars — full core 3.9 KB gzip. All effects respect prefers-reduced-motion and render complete without JS.