Scroll Rail

01

Listen first

Every project opens with a week of questions and no drawings at all.

02

Draw by hand

Early ideas stay on paper, where they are cheap to change.

03

Build a model

Card and timber models tell the truth about light and scale.

04

Make it real

The same small team stays with the work until the keys are handed over.

05

Come back

A visit a year later, to see how the place is being lived in.

About this component

Scroll Rail

A horizontal rail that carries any content sideways: chapters, a timeline, case studies or cards. Travel comes from a number or a live scroll value, or the rail drifts slowly on its own. Inside a panel, data-rail-depth makes an element drift against the travel for depth and data-rail-focus dims it until its panel reaches the middle. One animation loop writes transforms on whole pixels and pauses offscreen. Reduced motion turns the rail into a plain horizontal scroll.

Usage

The import and the props worth knowing about, in one place.

import { ScrollRail } from "@/components/beste/component/scroll-rail";

<ScrollRail className="h-[32rem]" gap={48}>
  <div className="w-[26rem]">
    <span data-rail-depth="0.3" className="text-7xl">01</span>
    <h3 data-rail-focus="0.4">Listen first</h3>
  </div>
  <div className="w-[26rem]">
    <span data-rail-depth="0.3" className="text-7xl">02</span>
    <h3 data-rail-focus="0.4">Draw by hand</h3>
  </div>
</ScrollRail>

// Driven by scroll: pass a framer-motion MotionValue (or any { get() }) as progress
const { scrollYProgress } = useScroll({ target: ref, offset: ["start start", "end end"] });
<ScrollRail progress={scrollYProgress} autoplay={false}>{panels}</ScrollRail>

Props

Read from the component's own type, so this cannot drift from what it accepts.

PropTypeDefaultDescription
childrenReactNode—The panels along the rail, in order. Each child is one panel and sets its own width. Inside a panel, `data-rail-depth="0.3"` makes an element drift against the travel and `data-rail-focus="0.35"` dims it until its panel reaches the middle.
gapnumber—Space between panels in pixels; narrow screens use less.
align"start" | "center" | "end" | "stretch"—Where panels sit vertically inside the rail.
progressnumber | ScrollRailProgressSource—Travel along the rail from start (0) to end (1): a number or a live source such as a scroll MotionValue.
autoplayboolean—Drift slowly along the rail and back on its own. Defaults to on when no progress is given.
speednumber—Pace of the autoplay drift.
smoothingnumber—How softly the rail follows its progress, 0 (instant) to 1 (very soft).
pausedboolean—Stop the rail where it is.
classNamestring—

More Media components

View all Media
Swimmers seen from above near a rocky shoreline

Low tide

Chet Baker, 2023

A pebble beach curving along a turquoise bay

The long bay

Nina Simone, 2022

Swimmers in a narrow rocky bay below pine trees

Under the pines

Miles Davis, 2024

A deep turquoise inlet between two cliffs

Inlet

Joni Mitchell, 2024

A limestone cove with clear green water

Green water

Bill Evans, 2023

A model in wide striped trousers leaning on a teal wallA glass perfume bottle casting amber shadows on warm paperA woman in a dark check coat walking down a city streetOrange poppies against a clear blue skyA singer with one hand raised in stage smoke and red light
A model in a bright yellow fleece set on a concrete courtA red swing carousel spinning against a pale skyA woman with short hair looking back over her shoulderA dropper bottle of golden oil on a round wooden boardA model in a red jersey and black jacket against a teal sky
HorizonA mountain valley and lake at first light