Feature Playground

Data-viz / scrollytelling · 12.2

Scroll-filled funnel

Pouring liquid into a measuring jug as you scroll.

Bars that fill with the section's scroll progress, turning a static metric into something scroll drives.

4 knobs

How it actually works

The cheapest feature in our own shipped set and one of the strongest. It is worth being precise about why it counts as a feature at all: a bar that fades in was always going to look like that. A bar that fills is showing you a quantity you could not otherwise see happen.

Bars scaleX() from the section's scroll progress with transform-origin: left, driven off the shared rAF, IntersectionObserver-gated, snapped to the correct extreme on leave. Vanilla, no library. It is the simplest possible demonstration of scroll driving a state machine, as opposed to parallax, which drives nothing.

The knobs, named

Fill curve, per-bar stagger, progress range mapping, origin. Four numbers, all measured on the real build.

KnobSourceWhat it teaches
Fill curve sourced How progress becomes fill. Linear is the honest one for a metric, and that is a real argument.
Per-bar stagger sourced How much later each bar starts. This is what makes it read as a funnel rather than a bar chart.
Progress range sourced What fraction of the section's scroll is spent filling. Below 1 the bars finish before you leave, which is usually what you want.
Origin sourced Where the fill grows from. Centre turns a funnel into a diverging chart.

sourced means the source names this parameter. ours means the source names none and the knob is our design against the mechanism. No knob here is invented and passed off as sourced.

Evidence

VERIFIED (ours, shipped)

Shipped in our own portfolio page, live at tabblabs.net/andrew (feature block B of its script).

Seen on
tabblabs.net/andrew (ours). Reusable for any funnel, metric, or before-after proof.
Dependencies
vanilla: one shared rAF
Difficulty
trivial-to-moderate
Performance
Transform-only, IO-gated, effectively free.
Accessibility and the floor
The bars render complete under .anim-gating. Each carries its real value in text, not only in width.

Notes

Composability. Put it inside 1.15's pinned composition as a phase and the funnel becomes an argument instead of a chart.

Under .anim-gating the bars render complete. For a metric this is not an accessibility nicety, it is a correctness requirement: the data must never be hidden behind the animation. A chart that is empty without JavaScript is not a chart, it is a decoration that happens to contain numbers.