152

Horizontal Card Track

£7 or the whole Vault, £79.20

A pinned horizontal scroll section where the cards hang from a real line, built on GSAP ScrollTrigger, Draggable and InertiaPlugin: the cord sags, stretches and waves with the row, and every card swings from its peg.

ScrollTriggerDraggableInertiaPlugin Lenis intermediate
8 more details
horizontal-scrollpinningscrubdraggablemomentumphysicsrope-physicskeyboard-navigation

This demo reads better at your own screen size than in the frame below:

Released

About this effect

Horizontal Card Track is a horizontal scroll section with a clothesline at its heart. A row of project or product cards hangs from a cord across the screen, each card on its own peg, and as the visitor scrolls down the section pins and the row travels sideways along the line. When the last card arrives the page carries on as normal.

Read the full effect overview

The line behaves like real cord. At rest it sags under the cards' weight in a gentle curve. Move the row quickly and the cord pulls tight and flat, the dips under the cards trailing behind them; stop, and a wave runs along the line, bounces off the ends and settles. Every card swings from its peg as a pendulum: it lags behind when the row sets off, swings past when it stops, leans into the air at speed and flutters slightly on a hard throw. Larger cards are heavier and swing more slowly. Once everything is still, every card hangs perfectly straight, so the text is never left at a tilt.

The visitor can take hold of the line. Grab the row and the cord dips toward the pointer as the row follows the hand; throw it and it glides on with momentum, moving the real page scroll so the row, the pin and the scrollbar always agree, then settles softly on the nearest card. Pull down on the cord itself and let go, or sweep the mouse across it, and the line twangs and the cards rattle on their pegs.

Built on GSAP ScrollTrigger, Draggable and InertiaPlugin. Each card still reveals as it comes in from the right, a progress rail shows where you are, and the keyboard moves card by card. The demo is a line of recent jobs from a Risograph and letterpress studio, pegged out to dry.

Horizontal Card Track - GSAP animation effect preview

What's included

15 items
  • Built on GSAP ScrollTrigger, Draggable and InertiaPlugin
  • Pinned section where vertical scroll moves a row of cards sideways along a hanging cord
  • The cord sags under the cards' weight, pulls tight at speed and sends a wave along the line when the row stops
  • Each card swings from its peg with real weight: heavier cards swing slower, a fast throw adds a slight 3D flutter
  • Cards always come to rest hanging exactly straight, so text is never left tilted
  • Grab the row and the cord dips toward the pointer; throw it with momentum and it settles on the nearest card
  • Pluck the cord, or sweep the mouse across it, to rattle the cards
  • Throws move the real page scroll, so wheel, drag and scrollbar never disagree
  • Options for cord stiffness, sag depth and swing
  • Per-card reveals as each card arrives: image, title lines and a counting figure
  • Progress rail with the current card number and a button for every card
  • Tab and the arrow keys move card by card
  • Below 768px a native horizontal scroller with scroll snap, the cord answering the swipe
  • Reduced motion keeps the sideways scroll with a straight line and still cards
  • Without JavaScript the row is an ordinary horizontal scroller under a drawn line

Perfect for

4 use cases
  • A selected-work section on a studio or agency home page, between the hero and the services
  • New arrivals or a collection row on a shop home page
  • Case studies, events or articles where several cards should be compared side by side
  • A portfolio that needs a horizontal scroll moment without giving each project a whole screen

How it works

3 sections

ScrollTrigger pins the section and scrubs the row sideways against the vertical scroll, with the pin length worked out from the width of the cards. The cord is a small physics simulation anchored just past both edges of the stage: the cards weigh it down where their pegs sit, the row's speed adds tension, and every change travels along it as a wave. It is redrawn as a smooth curve on every frame.

Each card is a pendulum hung from its point on the cord. The row's acceleration, the air at speed and the cord's own movement all swing it, and it settles under gravity until it hangs straight. Draggable and InertiaPlugin handle the grab and the throw, which drive the page scroll rather than the row, so the pin always follows. The simulation runs only while the section is on screen and goes quiet once everything is still.

Below 768px the pin is not created at all: the row scrolls natively with CSS scroll snap, and the cord and cards follow the speed of the swipe.

Plugins ScrollTrigger, Draggable, InertiaPlugin
Difficulty Intermediate
Smooth scroll Lenis integration
Includes HTML + JS + CSS source, documentation, AI setup prompt, lifetime updates

Lighthouse, as measured

Google Lighthouse on this effect's demo, from the latest scan. A measurement of the demo as shipped, not a promise for your page.

Accessibility
100
Best practices
100

No performance score, on purpose. That figure depends on how you deploy: your server's compression and caching, your CDN, the connection and the device doing the test, none of which the code controls. The same page can score very differently on two consecutive runs, so measure it where it will live.

Paid effect

Purchase to unlock the code.

Buying Horizontal Card Track opens the HTML, CSS and JavaScript source, the full documentation, an AI setup prompt for your editor, and every update we ship to it. Standard license: unlimited personal and commercial projects. Every paid product is tested for desktop and mobile layouts, reduced-motion handling, animation cleanup and keyboard controls wherever there is something to operate.

£7 Standard license, unlimited projects

Browse free effects

Or the whole library: the Vault, £79.20, one payment.

Documentation

Quick Start

1. Add to your HTML <head>:

Code snippet omitted: it ships with the download.

2. Add before the closing </body> tag:

Code snippet omitted: it ships with the download.

3. Add the section to your <body>, between your ordinary content:

Code snippet omitted: it ships with the download.

Using It With Your Own Design

What the effect needs from your markup: data-hct on the section that pins, data-hct-track on the row that moves (a direct flex row of cards inside a clipping stage), data-hct-card on every card, and the data-hct-rope svg inside the stage, holding one path marked data-hct-rope-path. The script redraws that path every frame; each <use> of it is a layer of the cord (the demo adds a soft shadow under the cord, and a lighter twist marked data-hct-rope-braid that travels with the row). Give the path id a unique name if the page has more than one track. Cards can be links, buttons or plain articles with tabindex="0". Everything else is optional and only animates if it is there: data-hct-media (the frame that unclips), data-hct-line (each title line, inside its own clipping parent), data-hct-count="1440" (a number that counts up to that value), data-hct-fade (fades up), and in the rail data-hct-progress, data-hct-current and data-hct-ticks, which gets one .hct-tick button per card.

What is only the demo's styling: the Ropewalk Press palette, Bricolage Grotesque and Martian Mono, the cord's colours, the wooden pegs and their springs, the ink chips, the house-colour and closing cards, the cue line and the short tail after the section. Replace all of it.

CSS the effect depends on:

  • The section is the viewport's height (height: 100svh), so the pinned view shows the whole row.
  • The stage clips sideways only: overflow-x: clip keeps swinging cards visible above and below and stops the browser scrolling the stage when a card takes focus.
  • The track is a native scroller by default (overflow-x: auto, scroll-snap-type: x mandatory); the script adds .hct-is-pinned at 768px and up, where the track must be overflow: visible. Keep both rules.
  • --hct-rope-y on the stage is where the cord is anchored (24px) and --hct-grip how far above each card its peg grips the cord (12px). The track's top padding is their sum, so the cord meets every peg, and each card's transform-origin is its grip point. The script reads both values.
  • Leave bottom padding on the track (104px in the demo, 88px on phones). A resting card hangs as far below its layout position as the cord sags, plus its swing; without the room it covers whatever follows or, in the native scroller, is clipped.
  • The script owns each card's transform (drop, swing and flutter). Put any transform of your own on an element inside the card.
  • The pre-hide rules under .has-js inside prefers-reduced-motion: no-preference set each reveal's start state. Keep them matched to the reveal, or delete both.
  • Images inside cards need draggable="false" and pointer-events: none, or the browser's own image drag fights the throw.

Options

Attribute Values Default Description
data-hct-snap true, false true Settle on the nearest card edge after a scroll or a throw
data-hct-drag true, false true Grab and throw the row (pinned mode)
data-hct-speed Number 1 Sideways pixels per pixel of vertical scroll; 2 makes the pin half as long
data-hct-swing Number, 0 upwards 1 How far cards swing; 0 keeps them hanging straight on a moving cord
data-hct-rope 0.25 to 3 1 Cord stiffness: higher is tighter, with quicker, smaller waves
data-hct-sag Pixels, 0 upwards 56 How far the cord sags under the cards at rest; 0 keeps it straight
Custom property Default Description
--hct-card-w 336px Base card width (.job--wide and .job--narrow scale it)
--hct-gap 28px Space between cards
--hct-accent #00a95c Active tick, house card, focus ring
--hct-reveal 1.05s Length of each card's reveal

Accessibility

  • Keyboard: Tab moves card by card; with focus on a card, the arrow keys, Home and End move to the next, previous, first or last card. The page scrolls so the pinned row brings the focused card into view. Every rail tick is a real button.
  • Touch: on tablets the row can be dragged sideways while vertical swipes still scroll the page. Below 768px there is no pin: the row is a native horizontal scroller with scroll snap, and the cord and cards answer the speed of your swipe.
  • Reduced motion: the row still moves with the scroll (that is how you reach the cards), but the cord is drawn straight, the cards hang still, and the reveals, snap and throw momentum are off.
  • No JavaScript: the row is an ordinary horizontal scroller under a straight drawn cord, with every card fully visible.
  • Text at rest: once the row, cord and cards are still, every card is set exactly upright, so nothing is left reading at a slight tilt.
  • Counting numbers: keep a visually hidden copy of the final figure for screen readers and mark the counting copy aria-hidden="true", as in the demo.

Dependencies

Required:

  • GSAP 3.12+ (the demo is built against 3.15.0)
  • ScrollTrigger

Optional:

  • Draggable and InertiaPlugin for grab and throw. Without them the row works with scroll and keyboard only, and the cord still answers the scroll, a pluck and the mouse.
  • Lenis 1.3+ for smooth scrolling (the demo pins 1.3.17). Opt out with data-smooth="off" on <html>.

Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.