vidscroll/core
The controller behind the React component and the element, for full control from JavaScript.
createScrollVideo is the controller that ScrollVideo and <vid-scroll>
are built on. Use it when you want to write the markup yourself, wire vidscroll
into a framework’s own lifecycle, or build your own loader UI. For most pages
without React, the element is simpler.
Set it up
-
Install vidscroll. The core entry doesn’t include React.
npm install vidscrollpnpm add vidscrollyarn add vidscrollbun add vidscroll -
Write the markup. A container with a stage inside. The stage is the part that stays pinned; an overlay inside it holds content over the video.
index.html<div id="hero" data-vidscroll> <div data-vidscroll-stage> <div data-vidscroll-overlay> <h2 class="title">Open water</h2> </div> </div> </div> -
Create the controller.
main.jsimport { createScrollVideo } from "vidscroll/core"; const hero = document.getElementById("hero"); const video = createScrollVideo( { container: hero, stage: hero.querySelector("[data-vidscroll-stage]") }, { src: "/videos/hero.mp4", length: "400vh", easing: "inOutSine" } );
The controller adds the video element to the stage, sets the container’s
height, and starts loading. The data-vidscroll attributes connect your markup
to vidscroll’s default styles, which are added to the page’s <head> once.
Options
The second argument takes the same options as the ScrollVideo props: src,
length, easing, fit, poster, optimize, smoothScroll,
fullPreload, fps, smoothingTauMs, warmup, debug, onLoad and
onError. They’re explained on the ScrollVideo
page.
To change them later:
video.update({ easing: "outCubic" });
video.setOptions({ src: "/videos/other.mp4", length: "300vh" });update changes only the options you pass; setOptions replaces all of them,
so anything you leave out goes back to its default. Changes apply the same way
as prop changes in React.
Controller
| Method | What it does |
|---|---|
on(event, fn), off(event, fn) | Listen to events (below). Listeners stay attached for the controller’s whole life. |
getState() | Progress, time, frame, duration and active sections. |
isReady() | Whether the video is loaded and following the scroll. |
getLoader() | The current loading state, or null. |
scrollToTime(seconds, options?) | Scrolls the page to that point in the video, smoothly by default. |
scrollToProgress(p, options?) | Scrolls to a progress from 0 to 1. |
addSection(range), removeSection(id) | Track a range of the video, such as { id: "intro", fromTime: 0, toTime: 4 }. Ids must be unique. |
getSectionProgress(id) | That section’s progress, 0 to 1. |
update(options), setOptions(options) | Change options, above. |
destroy() | Stop everything and remove the video. Call it when the content goes away. |
Events
| Event | Payload | When |
|---|---|---|
update | state | Every frame while the video moves |
ready | state | The video is loaded and following the scroll |
loader | loading state or null | The loading state changes |
sectionEnter, sectionExit | { id, state } | A section becomes active or inactive |
warmup | { value } | Progress of the pass over the timeline while loading |
resize | state | The window is resized |
Sections work like this:
const title = document.querySelector(".title");
video.addSection({ id: "title", fromTime: 0, toTime: 4 });
video.on("sectionEnter", ({ id }) => id === "title" && title.classList.add("visible"));
video.on("sectionExit", ({ id }) => id === "title" && title.classList.remove("visible"));Your own loader
The core has no loading UI. The loader event gives you the same state the
React loader receives, with phase (download, optimize, preparing or
error), progress from 0 to 1, and background, which is true while the
original video is already scrollable during a re-encode:
const bar = document.querySelector(".loading-bar");
video.on("loader", (state) => {
bar.hidden = !state || state.background;
if (state) bar.style.width = `${Math.round(state.progress * 100)}%`;
});In a framework
Create the controller when the markup is on the page, pass changes to update
or setOptions, and call destroy when the component goes away. That’s all
ScrollVideo itself does in React.
Styles
createScrollVideo adds vidscroll’s default styles to the page’s <head> once.
They’re also exported as a string, styles, if you want to read or copy them.
Every rule has zero specificity, so your own CSS always wins.
Related
<vid-scroll>: the element built on this.- How it works: what the controller does on each frame.