Fullscreen Video Slideshow with BigVideo.js

A tutorial about how to create a slideshow-like fullscreen video background using BigVideo.js, a jQuery plugin for big background video.
Fullscreen Video Slideshow with BigVideo.js

From our monthly sponsor: Create your beautiful portfolio website with Squarespace. Start your free trial.Advertisement

(Please note that the ZIP file does not contain any video files due to their size.)

BigVideo.js is a jQuery plugin that makes it easy to create fit-to-fill background video on a web page. It can play silent ambient background video (or series of videos), or used as a player to show video playlist.

In this tutorial, we’ll be creating a page that shows a series of video screens, showcasing the free HD stock video footage and animated backgrounds available on Beachfront B-Roll.

Before we get started, give some thought as to whether using this technique at all is appropriate for your project. Background video is bandwidth heavy and can be a big drag on the user’s browser performance. If your site is already video-heavy or incorporating big video is essential to the design and purpose of your site, then using this technique may be a great choice. However, if you can accomplish the same goal with using cinemagraphs for example, maybe that is a better choice. This tutorial is can be helpful to you in either case, as we cover using big background images as well.

The first thing you’ll need to do is get video content. In this case, we went to Beachfront B-Roll and downloaded a few of their free videos. Some of them were quite large in file size, so I used Quicktime Pro to trim them to about 10 seconds or so in length. For each of the videos, we will also need to create a poster image image of the first frame of the video. I used Photoshop to save a 960×540 jpeg for each image. I used a trick of applying a .5 pixel blur and a quality setting of 50 to get a smaller file size (afterall, these are background images, so having a little blurriness on them is not a bad thing).

The Markup

First, let’s do the markup for the page:

We have a header on the center of the screen. Then we have a wrapper div that contains all the different video screens. Then, there is a button we will use to navigate between the screens.

<header>
    <h1>Fullscreen Video Slideshow <span>with BigVideo.js</span></h1>
    <p>The videos in this demo are from <a href="http://beachfrontprod.blogspot.com" target="_blank">Beachfront B-Roll</a>, a great place to download unique HD stock video footage and animated backgrounds for any production purpose (for free!).</p>
    <p><small>A demo for</small> <a href="http://dfcb.github.com/BigVideo.js/" target="_blank">BigVideo.js</a> <small>by <a href="http://twitter.com/johnpolacek" target="_blank" rel="author">@johnpolacek</a></small></p>
</header>

<div class="wrapper">
    <div class="screen" id="screen-1" data-video="vid/bird.mp4">
        <img src="img/bird.jpg" class="big-image" />
        <h1 class="video-title">#1 Bird</h1>
    </div>
    <div class="screen" id="screen-2" data-video="vid/satellite.mp4">
        <img src="img/satellite.jpg" class="big-image" />
        <h1 class="video-title">#2 Satellite</h1>
    </div>
    <div class="screen" id="screen-3" data-video="vid/camera.mp4">
        <img src="img/camera.jpg" class="big-image" />
        <h1 class="video-title">#3 Camera</h1>
    </div>
    <div class="screen" id="screen-4" data-video="vid/spider.mp4">
        <img src="img/spider.jpg" class="big-image" />
        <h1 class="video-title">#4 Spider</h1>
    </div>
    <div class="screen" id="screen-5" data-video="vid/dandelion.mp4">
        <img src="img/dandelion.jpg" class="big-image" />
        <h1 class="video-title">#5 Dandelion</h1>
    </div>
</div>

<nav id="next-btn">
    <a href="#" class="next-icon"></a>
</nav>

The CSS

Before we get into the video, we need to style the page.

Since navigation will be handled by a single big next button, we set the body overflow to hidden. While we’re at it, we’ll make all text on the page white.

html, body {
    margin: 0;
    padding: 0;
    color: #fff;
    overflow: hidden;
    font-family: 'Open Sans Condensed', Arial, sans-serif;
    font-weight: 300;
    font-size: 1em;
}

Next, for the wrapper, we know we have five content screens, so we set the width to 500% (100% per screen) and the height to 100%. We are going to navigate the page by animating the wrapper’s horizontal position, so it will use absolute positioning. We’ll use a z-index of zero to keep the wrapper content in the background.

Note the data-video attribute. This is where our script will grab the url for the video for each screen.

.wrapper {
    position: absolute;
    width: 500%;
    height: 100%;
    z-index: 0;
}

We’ll position the header in the center of the page and make. Also, give it a high z-index so it stays on top of our background content.

header {
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 999;
    color: #fff;
    background: rgba(0,0,0,0.5);
    padding: 60px;
    width: 400px;
    height: 400px;
    border-radius: 50%;
    margin: -200px 0 0 -200px;
    text-align: center;
}

We want each screen to fill the height and width of the screen, so we set the height to 100%, and the width to 100% divided by the number of screens, in this case this results in 20%. Let’s set them to float left and make the positioning relative so we can absolutely position content inside the screens. We center the position of the image inside the screen div, so we keep the overflow hidden.

.screen {
    position: relative;
    height: 100%; 
    width: 20%; /*  NOTE:numVideos/100%  */
    float: left;
    overflow: hidden;
}

Inside the screen divs, we have a large image of the first frame of the video and a video title. For the image, we use min-width, min-height to make sure the size of the image is never smaller than the size of the .screen container div (which is always the size of the browser window) and set height and width to auto so the image’s aspect ratio is maintained.

.big-image {
    min-width: 100%;
    min-height: 100%; 
    height: auto;
    width: auto; 
}

Let’s put the video titles in the bottom left, make the font size really big and have them be 50% transparent.

.video-title {
    position: absolute;
    bottom: 5%;
    left: 5%;
    opacity: .5;
    margin: 0;
    padding: 0;
    line-height: .65;
    font-size: 4em;
    text-transform: uppercase;
}

Next up, the arrow button. I’ve made a pure CSS arrow button using a technique of putting a box with a border top and left, then rotating that box 45 degrees and putting it inside a div with a large border-radius turning it into a circle. (Note: We will make the rotation work by applying an IE filter for rotating 45 degrees from Boog Design’s excellent Matrix Calculator. See the head of the HTML for the conditional comment.)

nav {
    position:absolute; 
    right: 5%; 
    top: 45%; 
    padding: 20px; 
    background: #000; 
    border-radius: 40px; 
    opacity: .4; 
    cursor: pointer;}
    nav: hover {
    opacity: .6;
}

.next-icon {
    display: block;
    border-top: solid 2px #fff; 
    border-right: solid 2px #fff; 
    width: 20px; 
    height: 20px;
    position: relative;
    left: -5px;
    -webkit-transform: rotate(45deg);
    -moz-transform: rotate(45deg);
    -ms-transform: rotate(45deg);
    -o-transform: rotate(45deg);
    transform: rotate(45deg);
    color: #fff;
    text-decoration: none;
}

The JavaScript

Ok, here’s where we make stuff happen. First, link to all the scripts at the bottom of the page, before the closing body tag. Download the BigVideo.js Github Repo. In addition to BigVideo.js and its dependencies, we will be using jQuery Transit for animations.

<!-- BigVideo Dependencies -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/jquery-1.7.2.min.js"></script>')</script>
<script src="js/jquery-ui-1.8.22.custom.min.js"></script>
<script src="js/jquery.imagesloaded.min.js"></script>
<script src="http://vjs.zencdn.net/c/video.js"></script>

<!-- BigVideo -->
<script src="js/bigvideo.js"></script>

<!-- Tutorial Demo -->
<script src="js/jquery.transit.min.js"></script>

Before we get to the video, let’s set up navigation. We will need some vars to help manage navigation.

$(function() {
    var screenIndex = 1,
    numScreens = $('.screen').length,
    isTransitioning = false,
    transitionDur = 1000;
}

Let’s go over what these vars do.

  • screenIndex – keeps track of what screen we are looking at
  • numScreens – the number of screens (in our case 5)
  • isTransition – boolean to prevent extra clicking interfering with the navigation
  • transitionDur – how fast the animation scrolls

Now, add a next button click event and callback to do navigation.

$('#next-btn').on('click', function(e) {
    e.preventDefault();
    if (!isTransitioning) {
        next();
    }
});

function next() {
    isTransitioning = true;
    
    // update video index
    if (screenIndex === numScreens) {
        screenIndex = 1;
    } else {
        screenIndex++;
    }
    
    $('.wrapper').transit(
        {'left':'-'+(100*(screenIndex-1))+'%'},
        transitionDur,
        onTransitionComplete);
}

function onTransitionComplete() {
    isTransitioning = false;
}

Now, that our navigation is working, time to set up the video. When creating a video heavy site, it is important to consider mobile devices. Typically they do not support autoplay, meaning ambient background video will not work. There are tricks to get around this, but we should also consider that it is likely that the user is on a lower bandwidth connection. One thing to consider would be to provide non-video content to these users. In this demo, we will demonstrate how to do that using Modernizr, which you should link to in the document head.

First, add a var for BigVideo (BV) and an isTouch boolean to the top of our script, which gets set by Modernizr’s touch feature detection.

var screenIndex = 1,
    numScreens = $('.screen').length,
    isTransitioning = false,
    transitionDur = 1000,
    BV,
    isTouch = Modernizr.touch;
   

Next, initialize BigVideo for non-touch devices. Create a showVideo() function where we will grab the video filepath from the data-video attribute for the current screen being viewed. Add a showVideo() call to the onTransitionComplete callback function. Also, when the video is loaded and ready to play, we need to fade the framegrab image out. To do that, we use the Video.js api to add a ‘loadeddata’ event listener to the BigVideo player. We attach a callback function to that event which makes the image of the current screen fade out so the video is displayed.

var screenIndex = 1,
    numScreens = $('.screen').length,
    isTransitioning = false,
    transitionDur = 1000,
    BV,
    isTouch = Modernizr.touch;

// Next button click goes to next div
$('#next-btn').on('click', function(e) {
    e.preventDefault();
    if (!isTransitioning) {
        next();
    }
});

if (!isTouch) {
    // initialize BigVideo
    BV = new $.BigVideo({forceAutoplay:isTouch});
    BV.init();
    showVideo();
    
    BV.getPlayer().addEvent('loadeddata', function() {
        onVideoLoaded();
    });

    // adjust image positioning so it lines up with video
    $bigImage
        .css('position','relative')
        .imagesLoaded(adjustImagePositioning);
    // and on window resize
    $(window).on('resize', adjustImagePositioning);
}

// Next button click goes to next div
$('#next-btn').on('click', function(e) {
    e.preventDefault();
    if (!isTransitioning) {
        next();
    }
});

function showVideo() {
    BV.show($('#screen-'+screenIndex).attr('data-video'),{ambient:true});
}

function next() {
    isTransitioning = true;
    
    // update video index, reset image opacity if starting over
    if (screenIndex === numScreens) {
        $bigImage.css('opacity',1);
        screenIndex = 1;
    } else {
        screenIndex++;
    }
    
    if (!isTouch) {
        $('#big-video-wrap').transit({'left':'-100%'},transitionDur)
    }
        
    $('.wrapper').transit(
        {'left':'-'+(100*(screenIndex-1))+'%'},
        transitionDur,
        onTransitionComplete);
}

function onVideoLoaded() {
    $('#screen-'+screenIndex).find('.big-image').transit({'opacity':0},200)
}

function onTransitionComplete() {
    isTransitioning = false;
    if (!isTouch) {
        $('#big-video-wrap')
            .css('left',0);
        showVideo();
    }
}

Tidying up

You may notice that the big image and the big video don’t line up during the fade animation, resulting in a bothersome jump in position.This is because the video is centered inside the screen. To fix the problem, we need also need to center our images. To do that, we create a function that adjusts the positioning of the images.

function adjustImagePositioning() {
    $bigImage.each(function(){
        var $img = $(this),
            img = new Image();

        img.src = $img.attr('src');

        var windowWidth = $window.width(),
            windowHeight = $window.height(),
            r_w = windowHeight / windowWidth,
            i_w = img.width,
            i_h = img.height,
            r_i = i_h / i_w,
            new_w, new_h, new_left, new_top;

        if( r_w > r_i ) {
            new_h   = windowHeight;
            new_w   = windowHeight / r_i;
        }
        else {
            new_h   = windowWidth * r_i;
            new_w   = windowWidth;
        }

        $img.css({
            width   : new_w,
            height  : new_h,
            left    : ( windowWidth - new_w ) / 2,
            top     : ( windowHeight - new_h ) / 2
        })

    });

}

Call the function on document ready and attach it to a window resize event.

$bigImage
    .css('position','relative')
    .imagesLoaded(adjustImagePositioning);
// and on window resize
$(window).on('resize', adjustImagePositioning);

Now the images and videos should be aligned, resulting in a clean transition between the poster image and the video.

Please note that the ZIP file does not contain any video files due to their size.

Tagged with:

John is a Chicago-based web developer and designer working in the trenches doing big agency/big client work. In his spare time, he writes fun jQuery plugins like Scrollorama, draws indie comics and builds silly sites like areyouabrogrammer.com.

http://johnpolacek.com

Receive our bi-weekly Collective or official newsletter right in your inbox.

CSS Reference

Learn about all important CSS properties from the basics with our extensive and easy-to-read CSS Reference.

It doesn't matter if you are a beginner or intermediate, start learning CSS now.

Feedback 82

Comments are closed.
  1. Awesome tutorial…!!!
    One question: is it possible to also play the audio of the video?
    Thanks and once again: brilliant tutorial!

    • Change


      function showVideo() {
      BV.show($('#screen-'+screenIndex).attr('data-video'),{ambient:true});
      }

      to


      function showVideo() {
      BV.show($('#screen-'+screenIndex).attr('data-video'),{ambient:false});
      }

      in your HTML file and it will pay audio (but also show some kind of control panel). More information on the original project site: http://dfcb.github.com/BigVideo.js/

  2. downloaded the zip, then during extraction, you file prompted a warning of encryption loss does not work in Firefox under your current setup

  3. Preaty cool this bigvideo pluginโ€ฆ
    Is there a way to play also the audio & stop the loop.

  4. Hi, I tried this script and I must say it is very nice but I must say that I find some problems:
    1. Does not work with Opera browser (because it uses webm video)
    2. IE9 does not work in the loop mode
    3. does not work well in firefox (because it uses ogv video)

    You can solve these problems? you know how to fix these bugs?
    regards Alfonso

  5. Hi. This is an excellent tutorial.
    Can someone explain me why it’s not requiring all the other formats of video webm, flv, ogv?? Why it’s not working in mobile devices ( I tested on Android mobile phone )

    • If the condition if (!isTouch) { is commented I can see in my android mobile phone. But still in iPad and iPhone it’s not playing the video.

  6. Cool tutorial. The use of a circle background for the text is neat, but I don’t understand the header CSS that’s used to make it happen. I’ve checked with both Firefox and Chrome and they render it the same in that the resulting circle is 400x400px. The CSS suggests that with the extra 60px of padding on all sides of the header, it would cause the resulting circle to expand the circle an extra 120px. I don’t understand why that’s not happening.

  7. Hi,

    Is it possible to have the page auto link after a video is played to another page?

    If so, how would I code that?

    Thanks
    Chris

  8. Hi, thanx for this awesome tutorial ๐Ÿ˜€
    is that possible to make the slideshows auto play?

  9. Hello. On IE, the next button advances the video, but does not move the title. Do you have a solution?

  10. Hi,

    Thanks for the tutorial. I struggled before to combine bigvideo.js with a slider to achieve this effect, but I failed.

    I started with your tutorial and then added some content. Somewhere along the road I lost a feature, and I can’t bring it back. When I slide, the content slides, the video stays. When the transition is complete, the video changes for the one that should be in the new slide. So the old one is not pushed away, it just stays there until the new one is loaded.

    Can you think of any reason for this to happen ?

    Thank you,
    Andi Stancu

    • Update: I figured out the problem is about the way I call a specific slide number. If I use your next() function everything works well. This is how I do it: http://l.cq.tl/t5VK

      I’m currently trying to figure out a better way to call specific slides. Also, can you think of a solution to skip slides ? For example if I’m in slide 2 and I wanna go straight to slide 4 ? This way it would look more like the content loads from the side, rather then a full screen slider.

      Either way, thank you so much for this tutorial ๐Ÿ™‚

    • 1. In bigvideo.js, find and replace ‘body’ with your ‘div-name’.

      2. In bigvideo.css change the postion of big-video-wrap from fixed to absolute.

  11. Somehow this stopped working for me with Firefox 18.0 on Windows 7.
    Can anyone confirm?

  12. Hi…Its good , i need some help from all, iam a junior devoloper , hope you will solve my problem.

    1. how to play youtube videos as background (it saves bandwidth).

    2. auto play option for vedios.

    3. navigation for vedios.

    hope to here from you…Thanks in Advance

  13. Love what this script does! … but having a slight issue and wondering if you’ll help me out:
    I’m trying to play 4 different videos as backgrounds in 4 different divs using your script.
    I’ve placed the first frame/mobile image as a background of the 1st child div of the video div.
    I’ve set both divs to:

    position: relative;
    height: 100%;
    width: 100%;
    overflow: hidden;

    using html:

    doesn’t seem to work yet, the image shows fine, but the script isn’t making it disappear or play the video…

    How is the script supposed to look like for this (while using Modernizr)? ty

    this is what my script currently looks like:

    var BV = new $.BigVideo();
    BV.init();
    if (Modernizr.touch) {
    BV = new $.BigVideo({forceAutoplay:isTouch});
    BV.init();
    showVideo();

    BV.getPlayer().addEvent('loadeddata', function() {
    onVideoLoaded();
    });
    // adjust image positioning so it lines up with video
    $bigImage
    .css('position','relative')
    .imagesLoaded(adjustImagePositioning);
    // and on window resize
    $(window).on('resize', adjustImagePositioning);

    } else {

    function showVideo() {
    BV.show($('#big-video-play').attr('data-video'),{ambient:true});
    };
    };

    function onVideoLoaded() {
    $('#big-video-play').find('.big-video-wrap-image').transit({'opacity':0},200)
    };

  14. .. I’d edit my previous post if it’d let me but…
    another example of something I tried and failed was the following script,
    it did play the video but at the top of the main container.. not within the video’s container…
    any ideas?

    var BV = new $.BigVideo();
    BV.init();
    if (Modernizr.touch) {
    } else {
    BV.show($('#big-video-play').attr('data-video'),{altSource:$('#big-video-play').attr('data-video2')});
    $('#big-video-play').find('.big-video-wrap-image').transit({'opacity':0},200);
    }