The Scroll Builder¶
Almost everything you'll ever write for scrolling lives in the builder: a small chain of functions that describes what to scroll, how far, and how fast.
The builder doesn't actually scroll anything on its own. It produces a value that one of the three engines (Cmd, Task, Sub) can run. The same builder works in every engine - only the wiring around it changes.
Anatomy¶
Every scroll has the same shape:
View Source Code
scrollToSection : ScrollBuilder -> ScrollBuilder
scrollToSection =
Scroll.forContainer "container-id" -- 1. What surface to scroll (required)
>> Scroll.toElement "target-id" -- 2. Where to scroll to
>> Scroll.speed 300 -- 3. How fast (or use `duration`)
>> Scroll.easing QuintOut -- 4. How it should feel
>> Scroll.build -- 5. Finalize (required)
Only steps 1 and 5 (forContainer/forDocument and build) are mandatory. Everything in between is optional - but without a target, the scroll has nowhere to go.
1. Pick a Surface¶
A scroll runs against either the whole document or a specific scrollable element.
forDocument¶
Scrolls the page itself - the browser viewport. Use this for "jump to section" links inside a long article or single-page-app screen.
View Source Code
forContainer¶
Scrolls a specific element identified by its id. Use this for sidebars, panels, tables, image galleries, modals - anything with its own scrollbar.
View Source Code
2. Pick a Target¶
| Function | Scrolls to... |
|---|---|
toElement id |
The element with the given id (both axes, by default). |
toTop / toBottom |
The top or bottom edge of the surface. |
toLeft / toRight |
The left or right edge of the surface. |
toTopLeft / toTopRight / toBottomLeft / toBottomRight |
The named corner. |
toCenter |
The centre of the surface. |
toX n / toY n / toXY x y |
Exact pixel coordinates. |
toPercentageX n / toPercentageY n / toPercentageXY x y |
A 0–100 percentage of the scrollable area. |
Restrict to One Axis¶
toElement scrolls both axes by default. Add onXAxis or onYAxis to restrict it:
View Source Code
Useful if the container scrolls in both directions, but you just want to scroll to the vertical or horizontal position of the target.
Offset the Landing Position¶
withOffsetX, withOffsetY, and withOffsetXY shift the final scroll position. Useful for keeping sticky headers clear of the target:
View Source Code
3. Timing¶
Pick one of speed or duration.
| Function | What it means |
|---|---|
speed n |
Move at n pixels per second. The duration depends on how far we have to scroll. |
duration n |
Take exactly n ms, regardless of distance. |
delay n |
Wait n ms before starting the scroll. |
speed is almost always the right default for scrolling
A 100px scroll at a fixed 600ms duration crawls. A 2400px scroll at the same 600ms races. speed gives you the same feel no matter how far the user is jumping.
Gotchas
- If both
speedanddurationare set on the same target, the last one wins - be explicit about which you want. - With neither set, the engine treats the duration as
0msand snaps instantly to the target. Always set at least one.
Cmd and Task pre-calculate every frame up front, so the actual time the scroll takes can drift on busy pages or high-refresh-rate displays. Sub advances on real animation frames and stays accurate - reach for it if timing precision matters.
4. Easing¶
Easing controls the shape of the motion - whether the scroll whooshes off and glides to a halt, ramps up gradually, or bounces past before settling.
View Source Code
Defaults to Linear if you don't set one.
📖 See Easing for the full list and recommendations.
Multiple Scrolls in One Builder¶
You can chain several build calls into a single pipeline. Each one becomes a separate scroll - they can target different surfaces and have different settings:
View Source Code
How that runs depends on the engine:
Cmdfires both at once.Taskruns them in pipeline order, fail-fast.Subtracks each container independently.
Reusable Helpers¶
Extract recurring settings into a small helper and compose it into other builders:
View Source Code
Running a Builder¶
A builder is just a description. To actually make something move, hand it to one of the engines from update. Same builder, three wirings:
View Source Code
Next Steps¶
You've seen what the builder can describe. Next, pick the engine that fits your case.