vidscroll0.3.3

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

  1. Install vidscroll. The core entry doesn’t include React.

    npm install vidscroll
  2. 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>
  3. Create the controller.

    main.js
    import { 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:

main.js
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

MethodWhat 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

EventPayloadWhen
updatestateEvery frame while the video moves
readystateThe video is loaded and following the scroll
loaderloading state or nullThe loading state changes
sectionEnter, sectionExit{ id, state }A section becomes active or inactive
warmup{ value }Progress of the pass over the timeline while loading
resizestateThe window is resized

Sections work like this:

main.js
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:

main.js
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.