# Scroll Cinema

> Build scroll-driven "scroll-cinema" websites where scrolling scrubs a camera path instead of translating a document — pinned full-viewport stages, aperture/iris opens, continuous dolly moves, 3D card entries, stacked panels that dim as the next slides over, parallax copy, and masked staggered text reveals. Pure vanilla JS + CSS custom properties, no GSAP/ScrollTrigger/Lenis/Locomotive/Framer. Use…

- **Type:** Skill
- **Install:** `agentstack add skill-dhyey2907-claude-skill-scroll-cinema-claude-skill-scroll-cinema`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Dhyey2907](https://agentstack.voostack.com/s/dhyey2907)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Dhyey2907](https://github.com/Dhyey2907)
- **Source:** https://github.com/Dhyey2907/claude-skill-scroll-cinema

## Install

```sh
agentstack add skill-dhyey2907-claude-skill-scroll-cinema-claude-skill-scroll-cinema
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Scroll-cinema

Sites where the wheel drives a camera rather than the document. The whole
genre reduces to one primitive — **map scroll position to a number between
0 and 1, publish it as a CSS custom property, and let CSS do the rest** —
plus a catalogue of moves built on top of it.

Everything here is vanilla. Libraries are not needed for this and they cost
you 40–100 KB plus a scroll-hijacking layer that fights the browser.

## Start here

1. **Read `references/mechanics.md`** for the move catalogue with working
   code — aperture, dolly, parallax, 3D card entry, stacked panels, masked
   reveals, cycling readouts, progress rails.
2. **Read `references/pitfalls.md` before you debug anything.** It is a list
   of failures that look like logic bugs but are CSS-semantics or
   browser-lifecycle traps. Several cost real time to rediscover.
3. **`assets/template.html`** is a complete working page using every mechanic
   — single file, no dependencies, dark/light themed, with a toggleable
   overlay that labels each move as it fires. Copy it and replace the content,
   or lift individual mechanics out of it.

## The engine

Every stage is a tall section with a sticky child. The section's height is
the scroll budget; the sticky child is what you actually see.

```html

  

```

```css
.stage{position:relative}
.pin{position:sticky;top:0;height:100svh;overflow:hidden}
```

Progress is how far the section has travelled through its own scrollable
span:

```js
const r = stage.getBoundingClientRect();
const span = r.height - innerHeight;          // scrollable distance
const p = clamp(-r.top / span, 0, 1);         // 0 at entry, 1 at exit
stage.style.setProperty("--p", p.toFixed(4));
```

Then carve `p` into overlapping phase windows and publish each one:

```js
const sub  = (p,a,b) => clamp((p - a) / (b - a), 0, 1);  // remap a slice to 0..1
const ease = t => t * t * (3 - 2 * t);                    // smoothstep

stage.style.setProperty("--pOpen",  ease(sub(p, 0.08, 0.42)));
stage.style.setProperty("--pShear",      sub(p, 0.30, 0.46));
stage.style.setProperty("--pDolly", ease(sub(p, 0.38, 1.00)));
```

CSS consumes them directly, because unitless custom properties compose in
`calc()`:

```css
.orb   { transform: translate(-50%,-50%) scale(calc(.42 + var(--pDolly,0) * 9.4)) }
.copy  { transform: translateX(calc(var(--pShear,0) * -130%))
                    skewX(calc(var(--pShear,0) * -9deg)) }
```

Two things make this worth doing rather than reaching for a library:

- **Overlapping windows are what create the "one continuous camera" feel.**
  `--pShear` finishing at 0.46 while `--pDolly` starts at 0.38 means the
  headline is still leaving as the camera begins to move. Non-overlapping
  windows read as a slideshow; that is the single biggest quality difference
  between a cheap scroll site and an expensive one.
- **Keeping interpolation in CSS** means the compositor handles it. Your JS
  writes a handful of strings per frame and touches no layout.

Drive it with one listener for the whole page, coalesced through rAF:

```js
let queued = false;
function onScroll(){
  if (queued) return;
  queued = true;
  requestAnimationFrame(t => { queued = false; layout(t); });
}
window.addEventListener("scroll", onScroll, { passive:true });
window.addEventListener("resize", onScroll);
```

## Budgeting stage height

Scroll budget is pacing. Roughly **100vh of section height buys one second**
of comfortable screen time on a trackpad.

- A single mechanic (a card entering, a headline resolving): 60–150vh
- A stage with 2–3 overlapping phases: 250–450vh
- Anything over ~500vh feels like the page has stopped responding

Multi-panel stages divide their budget evenly: three stacked panels in a
400vh stage get ~133vh each. If a panel feels rushed, lengthen the stage
rather than compressing the other panels.

## Workflow

1. **Storyboard first, in words.** List the beats and what each one has to
   communicate. Motion that isn't carrying meaning is what makes these sites
   feel like showreels instead of sales tools.
2. **Build the engine and one stage.** Get progress publishing correctly and
   verify with a readout before adding a second mechanic — a wrong `span`
   silently pins everything at 0 or 1.
3. **Layer the phases** inside that stage, overlapping their windows.
4. **Add stages,** then tune the height budget by actually scrolling it.
5. **Do the fallbacks last but do not skip them** (see below).

## Non-negotiables

**Reduced motion needs a different layout, not faster animation.** A scrubbed
page with its transitions set to 0.01ms is broken — sticky stages stack into
an unreadable pile. Fall back to normal document flow: skip the `js` class
entirely so stages become ordinary sections.

```js
if (matchMedia("(prefers-reduced-motion: reduce)").matches) return;
document.documentElement.classList.add("js");
```

```css
:root:not(.js) .pin{position:relative;height:auto;min-height:100svh}
:root:not(.js) .panel{position:relative;transform:none;filter:none}
:root:not(.js) .reveal-line > span{transform:none;opacity:1;filter:none}
```

This doubles as the no-JS path, so the page is readable before the script
runs and if it never runs.

**Only animate `transform`, `opacity` and `filter`.** Anything touching
layout (width, top, margin) reflows every frame and the scrub will stutter.

**Use `100svh`, not `100vh`,** or mobile browser chrome crops every pinned
stage.

**Text over bright art needs a scrim.** A gradient overlay between the art
and the copy, not a text-shadow. This is the most common legibility failure
in the genre.

## What this cannot give you

Be straight with people about this, because it is the thing they are usually
actually asking. The motion system is fully reproducible from a prompt. The
*plates* are not — the rendered 3D scenes, the shot photography, the colour
grade that holds across sections. Procedural atmosphere (gradients, caustics,
dispersion, flares, starfields — all in `references/mechanics.md`) gets you a
long way and costs kilobytes instead of megabytes, but it is a different look
from rendered artwork, not a substitute for it.

The other half is art direction: which scenes, in which order, and the
judgement to cut one. A coding agent builds the camera. It does not decide
where to point it.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Dhyey2907](https://github.com/Dhyey2907)
- **Source:** [Dhyey2907/claude-skill-scroll-cinema](https://github.com/Dhyey2907/claude-skill-scroll-cinema)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-dhyey2907-claude-skill-scroll-cinema-claude-skill-scroll-cinema
- Seller: https://agentstack.voostack.com/s/dhyey2907
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
