Create your account

Already have an account? Login here

Note: By joining, you will receive periodic emails from Coursetro. You can unsubscribe from these emails.

Create account

Create an Awesome Scroll-based HTML5 Video Explainer

By Martin Wood - Jul 09, 2018

Today we're going to look at creating a very cool step by step "explainer", which features an embedded video of a hand counting the numbers 1, 2, 3, and 4! As we scroll down the page using the scrollwheel on our mouse, we can see that as we reach each of the next steps in the text section, the video plays along in sync to show the matching number on the hand.
This effect has been created entirely using HTML5, CSS, and a little JavaScript. No special libraries are needed for this neat little trick.

Credit must be given to this CodePen project for providing the JavaScript technique used in this tutorial!

Recording the video

We won't go into too much detail here about how to record the video, but for a quick explanation the video was created by filming the counting hand over a green screen, then using tools built in to Adobe Premiere, the green screen was removed and replaced with a nice blue background color, and then rotated and positioned in the video scene to where it looked good. The tools used in Premiere are "Ultra Key", which is what removes the green screen background, a color filter just to brighten things up a little bit, and finally a drop shadow just to add a little bit of depth to the video.

Once we have the video how we like it in Premiere, we can export it for our web page. For the sake of this tutorial the video has only been exported in MP4 format, however if you were doing this in production you would want to make sure to include other video formats such as OGG, and WEBM.

Setting up the project

The setup for this is very minimal. Open your code editor of choice, for this project we'll use Visual Studio Code, but any of your favourite text editor will work just fine too. Create an "index.html" file in the root, and add some basic HTML boilerplate code. In VSCode, we can type "!" then hit either Tab or Enter and it will create for us, this basic HTML.

<!DOCTYPE html>
<html lang="en">

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">




Let's also create an empty "main.css" file, and link that to our HTML with a standard link tag in the head section:

    <!-- Previous code removed for brevity -->
    <link rel="stylesheet" href="main.css">

We will also place the video file in the root directory which you can download here if you don't want to create your own.

First, let's get the HTML out of the way

To begin with we will write up the HTML code that we'll need to display the steps, and also contain the video we want to play back. Our "steps" we will wrap up in HTML5 "section" elements, which will include a main header for each step, and also a little bit of text to describe the step.

What will happen here is that each "container" class will be set to a specific height so that each of our steps matching up with the video correctly. Within that section, the steps themselves will scroll into view 1 by 1. We will also use the "sticky" technique from a previous tutorial which will cause the text to stick to the top of the container so that as we scroll down it remains visible until the next step scrolls into view. 

<section class="container">
    <div class="content">
        <h1>Scroll to Begin</h1>
        <p>Start it like this...</p>

We will repeat this for all 4 of our steps, and also include a start point before all the steps. Think of this as step zero, or an introduction before the actual steps. Make sure to change the heading for each new step to say something different.

After this, we will add the section for the video itself. First we will create a wrapper for the video with an ID of "set-height", this will essentially act as the "target" where our video will appear on screen. And below that we will embed the actual video itself, using our MP4 format (and any other formats that we want to include). We won't go into too much detail about the "source" tag here, but basically it contains some information telling the browser what file format it is, as well as what audio and video encoders it uses. After that is the path to the file itself. 

<video id="v0" tabindex="0" autobuffer preload>
    <source type='video/mp4;codecs="avc1.42E01E, mp4a.40.2"' src="fingers.mp4"></source>

This is all we need to get the video to load into the browser and to show on screen, so next we will include some JavaScript to control the video playback. 

Now for the JavaScript

Start by adding a script tag underneath the video file. Since we only have a small amount of JavaScript for this technique, we'll just add it as an inline script, but you can use an external file if you prefer. 

Inside this script tag we will first copy and paste the code from the Codepen link mentioned above, and then we'll make a small change to customise it to our needs. 

Below is the JavaScript after we have made our changes: 

var frameNumber = 0, // start video at frame 0
    // lower numbers = faster playback
    playbackConst = 1000, // Set to 1000 to make the playback slower
    // get page height from video duration
    setHeight = document.getElementById("set-height"),
    // select video element         
    vid = document.getElementById('v0');

// dynamically set the page height according to video length
vid.addEventListener('loadedmetadata', function () { = Math.floor(vid.duration) * playbackConst + "px";

// Use requestAnimationFrame for smooth playback
function scrollPlay() {
    var frameNumber = window.pageYOffset / playbackConst;
    vid.currentTime = frameNumber;


In the code we have made a change to the variable "playbackConst" from 500, to 1000. The lower the number here, the faster the playback will be, so feel free to experiment with this value to see the effect it has on the page. 

To briefly explain what this code is doing, to start we set variables which will hold the frame number of the playback, the playback speed, and the height of the page. The "setHeight" variable is dynamically set based on the height of the page will all the content in it, and is what is used to calculate the playback position relative to the scroll bar position. 
The event listener waits until the page has loaded enough information to get the total height. 
And the scrollPlay function is what makes the video play back and forth as we scroll around. 

Now we'll add a little CSS

The css for this project is going to be fairly simple, start by opening the CSS file we created earlier, then enter a couple of basic properties. We'll add a property for the body itself, which will set the background color to the same shade of blue that was used in the video, we'll set a font-family just to make the text look a little nicer, and a little bit of padding to keep the main content away from the edges. 

We'll also add a property for ID "v0" which means "video 0", and we'll set the position to fixed so the video remains in place as we scroll, and the bottom and right values will be 0 so the video will always stick to the bottom right of the browser, and finally a width of 100%

body {
    background-color: #c6d7de;
    font-family: sans-serif;
    padding: 3em;

#v0 {
    position: fixed;
    bottom: 0;
    right: 0;
    width: 100%;

At this point we can actually now open the page for the first time and see the start of our HTML coming together. Right click on the html file and click "Open with Live Server". (This step requires you have Live Server extension installed in VSCode. You can find it on the extensions tab, or use your preferred method of viewing a HTML file if you don't want this extension). 

First preview of project so far

You should be able to see the video being displayed, and as we scroll down the page the video playback should sync up with the scroll bar position. However, you'll see that the text we wrote earlier isn't currently visible, so we'll fix that next. 

Adding the remaining CSS

First, we need to make the text for the steps visible again. We can achieve this by simply adding z-index: 1 to the section element. We will also add position relative to make sure it sits where we want it to.

#set-height {
    display: block;

section {
    z-index: 1;
    position: relative;

Now we can see the text again, we'll make a few little style changes just to make the steps look nicer. We'll add a white background with rounded corners to the h1 element, and just some sizing to the paragraph to make it a little bigger.

h1 {
    font-size: 3em;
    background: #fff;
    display: inline-block;
    padding: 10px 15px;
    border-radius: 5px;
    margin: 0;

p {
    font-size: 1.5em;

So now you can see that our steps are looking a little nicer, but they're still all stuck to the top of the page and do not line up with the video in any way. In the next steps we'll look at fixing that. 

Our steps are now starting to look nice

We'll add some style to the content area of each section, and the first thing we'll do is add position sticky which will allow the content to "stick" to the middle until the next step comes into view. Remember, there is also a vendor prefix for this attribute which we will also add. We have also added some CSS properties to position the text where we want it (33% from the top).

.content {
    position: sticky;
    position: -webkit-sticky;
    width: 100%;
    top: 33.3%;

Next we'll set the height of each of our steps to make them line up with the steps in the video. Once we do that then we'll see the stick effect in action as well. Instead of adding a class or an ID to each section individually, we're going to use a CSS property called "nth-of-type" which allows us to select an individual instance of an element. 
We'll add this for all of our sections, including the intruduction before the steps. Each one of these will then have a height value set against it. The value for each of these was found mostly through trial and error as we need to change the height up and down until we find a value that's a good match for the video. Your values may not be the same, especially if you added your own style or different font-familt etc, so feel free to play around with these values. (The final value of 4000 is simply to make the last step last a really long time).

section:nth-of-type(1) {
    height: 1000px;

section:nth-of-type(2) {
    height: 1200px;

section:nth-of-type(3) {
    height: 1000px;

section:nth-of-type(4) {
    height: 1000px;

section:nth-of-type(5) {
    height: 4000px;

Now if we refresh our preview and start scrolling, we can see that the steps now line up with the video, and also that our "sticky" effect is working correctly. 
We can make the page look even nicer by adding some animation to it, and the first animation we'll add it to make the text appear to come into focus onto the screen. We will use the tool which is a really nice CSS animation generator. Simply pick the values you like, then copy the css code from the side. 

For this example, we used the options "Text", "Focus-in", "Text-focus-in, and just left all the other values on default. Feel free of course to play with any options you want if you prefer a different effect. After picking the options we want, simply click the "View code" button on the right hand side, and copy the CSS into your CSS file. We will also rename the class selector to "entered". Below this, we'll also copy the keyframes section which defines how the animation will work. 

.entered {
	-webkit-animation: text-focus-in 1s cubic-bezier(0.550, 0.085, 0.680, 0.530) both;
	        animation: text-focus-in 1s cubic-bezier(0.550, 0.085, 0.680, 0.530) both;

@-webkit-keyframes text-focus-in {
    0% {
        -webkit-filter: blur(12px);
                filter: blur(12px);
        opacity: 0;
    100% {
        -webkit-filter: blur(0px);
                filter: blur(0px);
        opacity: 1;
    @keyframes text-focus-in {
    0% {
        -webkit-filter: blur(12px);
                filter: blur(12px);
        opacity: 0;
    100% {
        -webkit-filter: blur(0px);
                filter: blur(0px);
        opacity: 1;

Right now we cannot see the effect but what we're going to do next is add a little bit of JavaScript, and with the help of a library called sticky.js we will apply the animation to each section as it scrolls into view. 

First, we download and add sticky.js to our project, which you can easily find here, and then add a reference to this file in our HTML file. Be sure to add this above our existing JavaScript, or it won't work. 

<script src="sticky.js"></script>

 Finally, to make the animation actually appear when we want it to, we're going to reference the function "enterView", passing in an object which tells the function what selector we want to target, and what the "enter" function will actually do. In our case, we want to target all our "section" elements, and the enter function is simply going to add "entered" to the element class list. This is the class we added earlier from animista. What this code does is tell sticky.js that whenever one of our sections comes into view, add the animation class we created earlier. At which point the CSS will take over and blur our HTML into view. 

    selector: "section",
    enter: function (el) {

// Previous code removed for brevity

And now, at last, if we refresh our live preview, we will see the final effect we want! As we scroll up and down the page, we'll see the video sync up with our steps on the left, and when we first scroll to each section, we have a nice fade in effect as the previous step leaves our screen!


To summarise, we have created a basic HTML page which features a "video explainer", a video of a fist counting off the numbers 1, 2, 3, and 4, and syncronising that with the corresponding steps on the left of the page. Using some basic CSS, and a little bit of JavaScript, we can quickly and easily create a really cool effect which you could use for perhaps a set of instructions, or a walkthrough of some kind. 

All the files shown in this tutorial can be downloaded from GitHub, so you don't have to create your own video file if you don't want to, so feel free to download the GitHub project and use the one created for this tutorial.

Share this post

Say something about this awesome post!