Scroll Effects On Videos With JavaScript
Published: 2024-03-06 17:34:06

by [Saleh Mubashar](https://blog.openreplay.com/authors/saleh-mubashar)


<blockquote><em>
Images and videos serve as crucial ingredients for crafting visually engaging websites. However, relying solely on static images and videos with manual controls can become monotonous. This article goes beyond the basics and explores how videos can be smoothly integrated with scrolling.
</em></blockquote>

<div style="background-color:#efefef; border-radius:8px; padding:10px; display:block;">
<hr/>
<h3><em>Session Replay for Developers</em></h3> 
<p><em>Uncover frustrations, understand bugs and fix slowdowns like never before with <strong><a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a></strong> — an open-source session replay suite for developers. It can be <strong>self-hosted</strong> in minutes, giving you complete control over your customer data.</em></p>
<img alt="OpenReplay" style="margin-top:5px; margin-bottom:5px;" width="768" height="400" src="https://raw.githubusercontent.com/openreplay/openreplay/main/static/openreplay-git-hero.svg" class="astro-UXNKDZ4E" loading="lazy" decoding="async">
<p><em>Happy debugging! <a href="https://openreplay.com" target="_blank">Try using OpenReplay today.</a></em><p>
<hr/>
</div>

Instead of just talking about typical scroll effects (like fade/slide in on scroll or scroll reveal animations), we'll look at how videos can become part of the scrolling experience, making websites more engaging. This involves manipulating video frames through scrolling, as well as pausing or playing a video when it comes into the page view, among other functionalities.


## Understanding the Video API

To implement scroll effects on videos using JavaScript, it's crucial to grasp the Video API, which provides a set of methods and properties for interacting with HTML video elements. 

Here's a straightforward method to showcase a video using the HTML ``<video>`` element:

```html
<video controls>
  <source src="video.mp4" type="video/mp4" />
  <source src="video.webm" type="video/webm" />
  <!-- fallback content here -->
</video>
```

The most important attribute here is `controls`. This attribute allows the user to play/pause and control other video elements. If you remove this, the user will have no manual control of the video.
The `<video>` element can contain two `<source>` elements so that different formats can be loaded depending on the browser viewing the site.


Now, let's look at the properties and methods that JavaScript provides. 

### Video Element Methods

* JavaScript Video Object: To manipulate videos in JS, we need to first access the video. You can use any JavaScript selection method here. In this case, we get the video using its id "videoID".
```javascript
const video = document.getElementById('videoID');
```

* Play and Pause: Using these functions, you can play and pause a video. These functions can be linked to custom buttons, for example.

```javascript
video.play(); 
video.pause();
```

* Load: You can reload a video using this method.

```javascript
video.load();
```

* Manipulate Controls: You can also manipulate the controls attribute through JavaScript.

```javascript
video.removeAttribute("controls");
```

### Video Element Properties

* Video Duration: This returns the total duration of the video in seconds.

```javascript
const videoDuration = video.duration;
```

* Control Autoplay: When loaded, you can get or set whether the video should start playing automatically.

```javascript
const AutoplayEnabled = video.autoplay;
video.autoplay = true; 
```

* Get and set volume: Get the current volume and also set it (from 0.0 to 1.0).

```javascript
const currentVolume = video.volume;
video.volume = 0.75; // Set volume to 75%
```

* Current Time: Jump to specific points in the video by manipulating the `currentTime` attribute.

```javascript
video.currentTime = 30; // set the playback time to 30 seconds
```

The `currentTime` attribute is particularly important for more complex animations as it can be linked to properties such as scroll values, etc.

### Video Event Listeners

There are also multiple video-specific event listeners that won't be used in this article but are good to know:

* `timeupdate`: Fired when the current playback position changes.
* `ended`: Fired when the video ends.
* `loadedmetadata`: Fired when the metadata (such as duration or volume) is loaded.
* `progress`: Fired as the browser loads the video data.



<CTA_Middle_Design />


## Playing Videos When Scrolled To

Now, let's create a practical example using our knowledge of the video API. Let's say you have a video on your site that you want to play automatically, but the video needs to be scrolled to. If we can detect when it comes into the user's view, we can start it directly, as opposed to having it play when it is not visible.

Firstly, to detect if the video is in view, we can use a simple formula:

```javascript
rect.top >= 0 &&
rect.left >= 0 &&
rect.right <= windowWidth &&
rect.bottom <= windowHeight
```
`windowWidth` and `windowHeight` represent the visible height and width of the browser window. The formula checks if all four sides of the video are within the viewport. If this condition is met, we play the video; otherwise, we pause it. This logic is encapsulated in a function named `isVideoInViewport`, linked to the scroll event.

`document.documentElement.clientWidth` ensures compatibility across various browsers, as some browsers may use one property while others use the alternative.


<iframe height="300" style="width: 100%;" scrolling="no" title="Autoplay video when in view" src="https://codepen.io/saleh-mubashar/embed/vYPgEYj?default-tab=js%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href="https://codepen.io/saleh-mubashar/pen/vYPgEYj">
  Autoplay video when in view</a> by Saleh-Mubashar (<a href="https://codepen.io/saleh-mubashar">@saleh-mubashar</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>
<br></br>

> **Note**: this pen is best viewed fullscreen.


## Manipulating Video Playback Position

Let's look at how we can control video playback using JavaScript. With this information, videos can be played based on, for example, scroll values or other forms of user input.

As discussed earlier, `video.currentTime` is essential. We can also control the playback rate using this line:

```javascript
// Set the playback speed to 1.5x
video.playbackRate = 1.5;
```

Let's create a simple example where the user can input a specific time, and the video will jump to that point. Firstly, we will get the user input (in seconds). Make sure to validate that the time is not less than 0 and greater than the video duration. We can then use `video.currentTime` to set the playback position. 

The demo and code can be seen below:

<iframe height="400" style="width: 100%;" scrolling="no" title="Video Playback from User Input" src="https://codepen.io/saleh-mubashar/embed/zYbNXqK?default-tab=js%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href="https://codepen.io/saleh-mubashar/pen/zYbNXqK">
  Video Playback from User Input</a> by Saleh-Mubashar (<a href="https://codepen.io/saleh-mubashar">@saleh-mubashar</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>


## Playing a Video Using Scroll Values

Now, let's get to the main example of this article. We will create a demo in which a video is played as the user scrolls. This will be done both forward and backward. This effect is very common and can give off an illusion of a 3d modal being moved on scroll. However, it is usually just a fullscreen video based on scroll values.

Let's look at the main steps we need to follow:

1. One initial challenge is the inability to create a scrollbar that mirrors the length of the video, allowing users to scroll through it using traditional HTML and CSS. To address this, we will implement a JavaScript function that dynamically adjusts the height of a div element encapsulating the video based on the video's duration. 
We will use the video `loadedmetadata` event listener for this. We also will use a speed constant variable in the formula. Increasing this constant will result in a longer scrollbar and slower video playback, while decreasing it will have the opposite effect.

```javascript
// get video element
const video = document.getElementById("myVideo");
const container = document.getElementById("videoContainer");

// set the container height according to video length
video.addEventListener('loadedmetadata', function() {
  const speed = 250; // can be any number (adjust to your preference)
  container.style.height = (video.duration * speed) + 'px';
});
```

2. Get the Scroll Y position and convert it into a percentage of the total page height. This is quite simple. We will create a function linked to the scroll event in which all the logic will be present. The formula will be something like this.
```javascript
// get current scroll progress
var scrollY = window.scrollY;
// get total page height and calculate percentage
var height = document.documentElement.scrollHeight - window.innerHeight;
var percentage = scrollY / height;
```
3. Use this calculated percentage to set the `currentTime` of the video, syncing the video playback with the scroll progress.
```javascript
// set video playback position.
video.currentTime = video.duration * percentage;
```

4. Smoothen things out: Lastly, we will use the `requestAnimationFrame` function to enhance the smoothness of video playback during scrolling.

```javascript
 window.requestAnimationFrame(playVideo);
```

The complete code and demo can be seen below:

<iframe height="350" style="width: 100%;" scrolling="no" title="Playing a Video Using Scroll Values" src="https://codepen.io/saleh-mubashar/embed/MWxpgwo?default-tab=js%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href="https://codepen.io/saleh-mubashar/pen/MWxpgwo">
  Playing a Video Using Scroll Values</a> by Saleh-Mubashar (<a href="https://codepen.io/saleh-mubashar">@saleh-mubashar</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>

## Conclusion

Adding scroll effects to videos is a fantastic way to elevate user engagement and enhance the visual appeal of websites. With the help of the Video API and JavaScript, you can integrate videos into the scrolling experience, providing users with a dynamic and engaging experience.

## Credits 
Both the videos used and this example are inspired by these two examples. A third is attached for further reference.

* [Play Video on Scroll! - by Jhett Lien](https://codepen.io/marduklien/pen/MdvdEG)
* [Video Blob Background for Scroll Control by - Shaw](https://codepen.io/marduklien/pen/MdvdEG)
* [Play Video On Scroll by - Malte](https://codepen.io/Maltsbier/pen/dyYmGGq)