A lightweight (<5KB uncompressed), zero-dependency web component that allows videos to scrub as you scroll the page.
Download the file scroll-scrub-video-component.bundle.js
and include it in the document head:
<script src="scroll-scrub-video-component.bundle.js"></script>
Or you can use it straight from unpkg:
<script src="https://unpkg.com/@chrishow/scroll-scrub-video-component@latest/dist/scroll-scrub-video-component.bundle.js"></script>
Expert mode: Alternatively, if you will be bundling the component into a javascript application, install using npm:
npm install @chrishow/scroll-scrub-video-component
And import the component into your app:
import 'scroll-scrub-video-component';
Add HTML elements for each component, like this:
<scroll-scrub-video src="./videos/my-video.mp4"></scroll-scrub-video>
The attribute src
is required. This is your video source.
You may optionally add two more attributes:
<scroll-scrub-video src="./videos/my-video.mp4" firefox-src="./videos/my-special-firefox-video.mp4" min-width="650"></scroll-scrub-video>
firefox-src
is the url to a specific video to be used on Firefox browsers. This is useful because videos with a
keyframe interval of 5 are fine on Chrome, Edge and Safari, but are very janky on Firefox. So you can specify a specific
(larger) file encoded with a keyframe interval of 1 just for Firefox.
min-width
allows you to specify a minimum window width in pixels, below which the element won't show, nor will it load the videos.
If the window width is later widened above the minimum, the videos will load and display automatically. You should make sure you have
your viewport correctly setup for this to work by adding this meta tag to the header:
<meta name="viewport" content="width=device-width, initial-scale=1">
To prevent a layout shift when the component initialises, you can add this to your CSS file:
scrub-video {
display: block;
min-height: 100vh;
}
The following CSS variables/custom properties can be added to the CSS in step 3 if you want more control over the component.
The default settings are shown in these examples.
These are the margins around the component before it is zoomed full-screen. You might want to tweak these to make it fit in with your page margins.
--unzoomed-margin-left: 5rem;
--unzoomed-margin-right: 5rem;
--unzoomed-margin-top: 3rem;
--unzoomed-margin-bottom: 3rem;
How many 'pages' you have to scroll through to scrub fully through one video.
--scrub-pages: 6;
The video is initially not shown, then faded in when it has fully loaded. This setting controls how quickly the video fades in.
--load-fade-duration: 0.2s;
How quickly the video zooms as it goes full screen
--zoom-duration: 0.2s;
You can use ffmpeg to encode videos suitably for the web component.
If you don't have ffmpeg installed, you can use this in-browser version which doesn't require you to install anything to your computer:
I recommend using these settings for the Chrome/Edge/Safari version:
ffmpeg -y \
-vcodec libx264 \
-i input.mov \
-vf scale=1920:-1 \
-crf 25 \
-g 5 \
-movflags faststart \
-pix_fmt yuv420p \
-an \
-preset 'slow' \
output.mp4
In this example:
input.mov
is the input file (this can be .mov, .mp4, .mkv, .webm etc)
-crf 25
is the compression setting, somewhere between 20 (small file, more compressed) and 30 (large file, very high quality) should work well.
-g 5
the 'max keyframe interval'
output.mp4
is your output file name.
For Firefox, I would change this to:
ffmpeg -y \
-vcodec libx264 \
-i input.mov \
-vf scale=1920:-1 \
-crf 25 \
-g 1 \
-movflags faststart \
-pix_fmt yuv420p \
-an \
-preset 'slow' \
firefox-output.mp4
You'll only need this stuff if you plan to modify the web component, nothing down here is needed just to use it.
npm install
Installs node dependencies.
npm run build
Builds the component.
npm run build:watch
Used to automatically rebuild the component as soon as any changes are made to the code.
npm run serve
Serves the component locally.
npm run build:bundle
Bundles the component into a single file (to dist/scroll-scrub-video-component.bundle.js).
npm run analyze
Builds a custom elements manifest (custom-elements.json) which can be used by IDEs for better auto-completion.