Immersive Video Template

Immersive Video Template

A full-screen video presentation, that is resized and animated to become the content of a mobile device.

Nucleo icons

Sponsored by Nucleo, a free application to collect, customize and export all your icons as icon font and SVG symbols. Made by the CodyHouse folks!

Do you want to include this resource in a product offered for sale? Learn more about our Extended License

Lately, we’ve come across a couple of websites using full-screen videos as a way to “dramatically” introduce a product or a feature of an app. We tried to create something similar, in the form of a simple application template.

With the help of some CSS tricks (mostly CSS transforms and animations), we’ve created a video introduction that turns into content for a mobile device. Some of the tricky parts were about picking the right assets (we’ve created this video that introduces some features of a photo editing app) and handling the loading animation. We’re aware that showing a loader right away is not a great experience. Therefore, before using this template you should consider 1) whether the video would be a great selling point or not, and 2) whether you expect many returning visitors, or the goal is just to let the user download the app and (almost) never come back. If the answers to these questions are 1) YES and 2) No, then this template will come in handy for you ;)

Video footage: pexels.com
Inspiration: Landing Page by Cuberto
Icons: Nucleo

Creating the structure

The HTML structure is composed of two main elements: a div.product-intro (product title, action button, ..) and a div.product-preview for the image/video preview of the product.

<div class="cd-immersive-video">
   <div class="intro-wrapper">
      <div class="product-intro">
         <div>
            <h1 class="item item-1">Immersive Video Template</h1>

            <p class="item item-2">
               <!-- product description here -->
            </p>

            <a href="#0" class="cd-btn item item-3">Download &amp; Article</a>
         </div>
      </div> <!-- .product-intro -->

      <div class="product-preview no-transition">
         <div class="device-frame">
            <img src="assets/img/mobile-frame.svg" alt="Device Frame">
         </div>

         <div class="product-image">
            <img src="assets/img/video-fallback.jpg" alt="Product Preview">
         </div>

         <div class="product-video" data-video="assets/video/video.mp4">
            <div class="video-wrapper">
               <!-- video will be insereted here using js -->
            </div>
         </div>
      </div> <!-- .product-preview -->
   </div> 

   <div class="cd-loader"></div>
</div> <!-- .cd-immersive-video -->

The video is not directly inserted in the HTML but it's loaded using JavaScript.

Adding style

On small devices (viewport width less than 800px), the css is pretty straightforward: both the div.product-intro and the div.product-preview are initially hidden ( opacity: 0 ) and then revealed using the cd-item-move-up animation.

@keyframes cd-item-move-up {
  0% {
    opacity: 0;
    transform: translateY(50px);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

The product preview video is not loaded on these devices while an image is used as a preview of the product (div.product-image > img).

On bigger devices, the product intro and preview are initially hidden; once the preview video has been loaded (more in the Events handling section), the .video-is-loaded class is used to reveal the content and trigger the video animation.

@media only screen and (min-width: 800px) {
  .cd-immersive-video .intro-wrapper {
    /* while loading the video - hide the content */
    visibility: hidden;
    opacity: 0;
    transition: opacity 1.5s, visibility 1.5s;
  }
  .cd-immersive-video.video-is-loaded .intro-wrapper {
    /* video has been loaded - reveal content */
    visibility: visible;
    opacity: 1;
  }
}

For the video animation: the div.product-video is initially scaled-up (using JavaScript) to cover the entire viewport. Once the video has been played for around 1s, the div.product-video is scaled down and translated to the right. The div.product-intro is then animated using the .animate-content class: each item of the intro (h1, p..) is revealed using the cd-item-slide-in animation with a different animation-delay.

@media only screen and (min-width: 800px) {
  .cd-immersive-video .product-intro .item {
    opacity: 0;
  }
  .cd-immersive-video .product-intro.animate-content .item {
    animation: cd-item-slide-in .4s both;
  }
  .cd-immersive-video .product-intro.animate-content .item-1 {
    animation-delay: .1s;
  }
  .cd-immersive-video .product-intro.animate-content .item-2 {
    animation-delay: .2s;
  }
  .cd-immersive-video .product-intro.animate-content .item-3 {
    animation-delay: .3s;
  }
}

Events handling

On big devices, we use jQuery to load the product preview video and insert it into the HTML structure.
We used the canplaythrough event to detect if the video is ready to be played; we also added a check to the readyState of the video  (if the video is cached the canplaythrough event may not be detected).

if( productVideo.is(':visible') ) { //productVideo = $('.product-video');
   //the video src is the data-video of productVideo
   var video = $('<video><source src="'+productVideo.data('video')+'" type="video/mp4" />Sorry, your browser does not support HTML5 video.</video>');

   //check if the canplaythrough event occurs - video is ready to be played
   video.on('canplaythrough', function() {
      video.off('canplaythrough').trigger('readyToPlay');
   });
   // if video is in cache 'canplaythrough' won't be triggered 
   if (video.get(0).readyState > 3) {
      video.off('canplaythrough').trigger('readyToPlay');
   }
}

Once the video is ready, we insert it into the HTML, hide the loader and then trigger the video animation.

video.on('readyToPlay', function(){
   //video id ready to play
   video.appendTo(productVideo.find('.video-wrapper'));

   //wait for the end of an animation iteraction and reveal the video
   loader.one(animationIteration, function() {
      loader.addClass('no-animation').off(animationIteration);
      //makes sure the transition is applied (when using the scale-down class)
      //https://css-tricks.com/restart-css-animation/
      void loader.get(0).offsetWidth; 
      loader.addClass('scale-down');
      loader.on(transitionEnd, function(){
         loader.off(transitionEnd);
         immersiveVideoWrapper.trigger('startAnimation'); //animate div.product-video
      });
   });
});

Join our newsletter

Get our monthly recap with the latest CodyHouse news