Rollercoaster
An orange two-wheeled cart rides a rollercoaster track (climb, big drop, dip, small hump) in 4 s, tilting its nose with the slope thanks to offset-rotate: auto, slowing at the start and the finish, then starts over: the only trajectory in the catalog where the object orients itself — CSS only, zero JavaScript, cart stopped mid-drop when the user reduces motion.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. 3D has 50 effects, including 8 free. Explore the category →
3 usage examples



How it works
The .fx-0040-root root (background #0a0a0f, at least 300 px tall) centers a 320 × 220 px .mp-roller-scene. An <svg> draws the track, ten quadratic Bézier curves in an amber line at 15%, and a second white line at 5%, the same shifted 4 px down: the double rail. The .mp-roller-car is a 20 × 14 px #f59e0b rectangle with rounded corners; its ::after pseudo-element draws a 5 px gray wheel and the second one with a box-shadow offset by 11 px.
The cart gets the track path as offset-path: path(…) and an offset-distance animation from 0 to 100% in 4 s, ease-in-out, looping. offset-rotate: auto turns it at every moment in the direction of the tangent: measured at four points of the ride, the angle of the car body follows the slope of the path within half a degree (68° versus 68.2° on the climb, 71.5° versus 71.6° on the big drop), identically in Chromium 151, Firefox 153 and WebKit 26.
offset-anchor: 50% 100% picks the point of the cart that sits on the path: the middle of the bottom of the body, not its center. The body therefore rides above the line, and the wheels, which stick out 4 px below the body, fall between the two rail lines; the cart also pivots around that point. The easing applies to the whole ride: slow start, full speed on the big drop, braking on the last hump, then the cart jumps back to the start.
Accessibility
- Reduced motion: under
prefers-reduced-motion: reduce, a block scoped to.fx-0040-rootstops the cart in the middle of the big drop (offset-distance: 50%), nose down: the still image still says "rollercoaster". Measured: 0% of pixels change over 0.8 s in Chromium, Firefox and WebKit, versus 0.75% in normal mode. - Decorative content: the scene carries no text; the svg and the cart, an empty
div, are ignored by screen readers. Write next to it what the track stands for (ride, mine gallery, slope). - Contrast: the orange cart measures 9.2:1 on the dark background; the track, at 15%, and the rail, at 5%, are deliberately faint. On a light background, darken and thicken them, as in the examples.
- Rhythm: a 4 s loop, no flashing; the return to the start is a jump of the cart.
Browser compatibility
CSS only: offset-path: path(), offset-rotate: auto, offset-anchor and animated offset-distance, no JavaScript, no dependency. Measured in Chromium 151, Firefox 153 and WebKit 26 (Safari's engine): same positions, same body angle, same stop under reduced motion. Not checked on a real Safari.
A browser that supports offset-path but not offset-anchor centers the body on the path: the cart still rides and tilts, the wheels pass just below the rail. Without offset-path, the cart stays still at the top left of the scene and the track stays drawn.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0040-root">
<div class="mp-roller-scene">
<svg viewBox="0 0 320 220" fill="none">
<path d="M10,180 Q40,180 60,120 … 300,140" … /> <!-- track -->
<path d="M10,184 Q40,184 60,124 … 300,144" … /> <!-- rail -->
</svg>
<div class="mp-roller-car"></div>
</div>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Cart color and shape (CSS — .mp-roller-car) |
20 × 14 px, #f59e0b, 4 px corners, orange glow | Change background, border-radius and box-shadow. If you change the size, keep the wheels (::after, bottom: -4px) under the body. |
Point on the rail (CSS — offset-anchor) |
50% 100% (middle of the bottom of the body) | 50% 50% centers the body on the line; 50% 18px puts the bottom of the wheels on the line. The cart pivots around this point. |
Orientation (CSS — offset-rotate) |
auto (follows the slope) | auto 180deg flips the cart (reverse); 0deg keeps it level, like a hanging gondola. |
Speed and easing (CSS — 4s ease-in-out) |
4 s, slow start and finish | linear gives a constant speed; cubic-bezier(.5,0,.8,.6) speeds up on the drop. 6 s for a quiet tour, 2.5 s for a thrill ride. |
| Track (HTML + CSS) | Climb, big drop, dip, small hump over 320 × 220 px | The path is written three times: the track line, the rail (same path, 4 px lower) and the offset-path. Change all three together. |
Background (CSS — .fx-0040-root) |
#0a0a0f | Change or remove the background; on a light background, darken and thicken the track and the rail. |
FAQ
offset-rotate: auto: the browser computes the tangent of the path at the point reached and rotates the element accordingly, at every frame. Nothing to compute, no JavaScript. Measured: the body angle follows the slope within half a degree in Chromium, Firefox and WebKit.linear; for a single run, use 1 and forwards instead of infinite.