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 & 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
});
});
});