• Transition Effect with CSS Masks
  • The Nuggets translation Project
  • Translator: luoyaqifei
  • Proofreader: Graning, Hyuni

Transition effects of CSS masks

A tutorial on how to use CSS masks to create some interesting visual sliding transitions. This tutorial is highly experimental!

See demo download source code

Today we want to show you how to create a fun, simple and eye-catching transition, using CSS masks. Like clipping, masks are another way to define visibility and combine it with an element. In the next tutorial we will show you how to apply a new property of modern transition effects to simple slides. We used the Steps () time function to apply the animation and move a mask PNG over an image for interesting transitions.

Note: Keep in mind that this effect is highly experimental and only supported by some modern browsers.

Review images

Remember that Firefox only partially supports it (it only supports inline SVG mask elements), so we now need a fallback mechanism, and soon we’ll be welcoming support from all existing browsers. Note that we added Modernizr to check for support.

So let’s get started!

Create a mask diagram

We will walk into the first example of this tutorial (Demonstration 1). _

To make the mask transition work, we need an image that hides/shows some part of the underlying image. The mask will be a PNG with transparent parts. The PNG itself is a Sprite image that looks something like this:

The black part shows the current image, while the white part (which is actually transparent) is the hidden part of the image, revealing the second image.

To create a Sprite image, we need to use this video. We imported it into Adobe After Effects to shorten the video, removed the white and exported it as a PNG sequence.

To reduce the length to 1.4 seconds, which is when we want the transition to happen, we will use the Time Stretch effect.

To remove the white part, we will use Keying -> extract and set the white point to 0. In the screenshot below, the blue part is our composite background, the transparent part of the video.

Eventually, we can save our composition in PNG sequences and use Photoshop or a tool like CSS Sprite Image Generator to generate individual images.

This is a Sprite image that was created to expose the effect for an organic look. We will create another “flipped” Sprite for the opposite effect. You can find all the different Sprite images in the img demo folder.

Now that we have the mask diagram created, let’s dig into the HTML structure in our simple slide show example.

tag

For our demonstration, we will create a simple slide to show the mask effect. Our slides will fill the screen, and we’ll add a few arrows that trigger the slide transitions. The idea is to overlap the slides and then change the Z-index of the next slide at the end of the animation. Our slide structure looks like this:

<div class="page-view">
    <div class="project">
        <div class="text">
            <h1>"All good things are<br>Wild & free"</h1>
            <p>Photo by Andreas R ø nningen</p>
        </div>
    </div>
    <div class="project">
        <div class="text">
            <h1>"Into the wild"</h1>
            <p>Photo by John Price</p>
        </div>
    </div>
    <div class="project">
        <div class="text">
            <h1>"Is the spring" coming?"</h1>
            <p>Photo by Thomas Lefebvre</p>
        </div>
    </div>
    <div class="project">
        <div class="text">
            <h1>"Stay curious"</h1>
            <p>Photo by Maria</p>
        </div>
    </div>
    <nav class="arrows">
        <div class="arrow previous">
            <svg viewBox="208.3 352 4.2 6.4">
                <polygon class="st0" points="212.1,357.3 211.5,358 208.7,355.1 211.5,352.3 212.1,353 209.9,355.1"/>
            </svg>
        </div>
        <div class="arrow next">
            <svg viewBox="208.3 352 4.2 6.4">
                <polygon class="st0" points="212.1,357.3 211.5,358 208.7,355.1 211.5,352.3 212.1,353 209.9,355.1"/>
            </svg>
        </div>
    </nav>
</div>Copy the code

This DIV page view is our main container, and it will contain all of our slide pages. The divs inside this project are the slide pages in our slides, each containing a title and a caption. Also, we will set up a separate background image for each slide page.

Arrows are used to trigger the next or the previous animation and to jump to and from the slide.

Let’s look at the style.

CSS

In this section, we will set up CSS for our effects.

We’ll create a typical full-screen slideshow layout with some centered headings and jump links at the bottom left of the page. Also, we will define some media queries to make mobile devices compatible with this style.

In addition, we set our Sprite images to a background that is not visible on our global container so that they can be loaded as soon as the page is opened.

.demo-1 { background: url(.. /img/nature-sprite.png) no-repeat -9999px -9999px; background-size: 0; } .demo-1 .page-view { background: url(.. /img/nature-sprite-2.png) no-repeat -9999px -9999px; background-size: 0; }Copy the code

Each slide page will have a different background:

.demo-1 .page-view .project:nth-child(1) { background-image: url(.. /img/nature-1.jpg); } .demo-1 .page-view .project:nth-child(2) { background-image: url(.. /img/nature-2.jpg); } .demo-1 .page-view .project:nth-child(3) { background-image: url(.. /img/nature-3.jpg); } .demo-1 .page-view .project:nth-child(4) { background-image: url(.. /img/nature-4.jpg); }Copy the code

The different backgrounds will of course be dynamically implemented by you, but in this tutorial we are interested in effects, so keep it simple.

We define a class called Hide, and whenever we want to hide a slide page, we add this class to the slide page. The definition of this class includes a Sprite image that we use as a mask.

Given that one frame takes up 100% of the screen and our animation contains 23 images, we need to set the width to 23 * 100% = 2300%.

Now we will use Steps to add our CSS animation. We want our Sprite image to stop at the beginning of the last frame. So, in order to do that, we need to count to 22 steps, one less than the total.

.demo-1 .page-view .project:nth-child(even).hide { -webkit-mask: url(.. /img/nature-sprite.png); mask: url(.. /img/nature-sprite.png); -webkit-mask-size: 2300% 100%; mask-size: 2300% 100%; - Webkit-Animation: mask-play 1.4s Steps (22) forward; Animation: Mask-Play 1.4s Steps (22) forward; } .demo-1 .page-view .project:nth-child(odd).hide { -webkit-mask: url(.. /img/nature-sprite-2.png); mask: url(.. /img/nature-sprite-2.png); -webkit-mask-size: 7100% 100%; mask-size: 7100% 100%; - Webkit-Animation: mask-play 1.4s Steps (70) forward; Animation: Mask-Play 1.4s Steps (70) forward; }Copy the code

Finally, we define the animation keyframe:

@-webkit-keyframes mask-play { from { -webkit-mask-position: 0% 0; mask-position: 0% 0; } to { -webkit-mask-position: 100% 0; mask-position: 100% 0; } } @keyframes mask-play { from { -webkit-mask-position: 0% 0; mask-position: 0% 0; } to { -webkit-mask-position: 100% 0; mask-position: 100% 0; }}Copy the code

Now that we’re here, we have a structured, stylized slide. Let’s add functionality to it!

JavaScript

We’ll demonstrate this using Zepto.js, a lightweight JavaScript framework similar to jQuery.

We start by declaring all the variables and setting the length and elements.

Then we initialize the event to get the current and next slide pages and set the correct Z-index.

Function Slider() {// length this.durations = {auto: 5000, slide: 1400}; // DOM this.dom = { wrapper: null, container: null, project: null, current: null, next: null, arrow: null }; // this. Length = 0; this.current = 0; this.next = 0; this.isAuto = true; this.working = false; this.dom.wrapper = $('.page-view'); this.dom.project = this.dom.wrapper.find('.project'); this.dom.arrow = this.dom.wrapper.find('.arrow'); this.length = this.dom.project.length; this.init(); this.events(); this.auto = setInterval(this.updateNext.bind(this), this.durations.auto); } /** * Set the initial z-indexes & get the current item */ slider.prototype.init = function () {this.dom.project.css('z-index', 10); this.dom.current = $(this.dom.project[this.current]); this.dom.next = $(this.dom.project[this.current + 1]); this.dom.current.css('z-index', 30); this.dom.next.css('z-index', 20); };Copy the code

We listen for the click on the arrow, and if the slide is not currently animated, we check to see if the click occurred on the next arrow or the previous arrow. Like this, we accept the value of the next variable, process it, and change the slide.

/ / slider.prototype. events = function () {var self = this; this.dom.arrow.on('click', function () { if (self.working) return; self.processBtn($(this)); }); }; Slider.prototype.processBtn = function (btn) { if (this.isAuto) { this.isAuto = false; clearInterval(this.auto); } if (btn.hasClass('next')) this.updateNext(); if (btn.hasClass('previous')) this.updatePrevious(); }; / * * * update after a global index * / Slider in prototype. UpdateNext = function () {this. Next = (enclosing the current + 1) % this. The length; this.process(); }; / update a global index before * * * * / Slider. The prototype. UpdatePrevious = function () {this. Next -- --; if (this.next < 0) this.next = this.length - 1; this.process(); };Copy the code

This function is the heart of our slide: we set the “hide” class to the current slide page, and once the animation is over, we decrease the previous page’s Z-index, increase the current page’s Z-Index, and then remove the previous page’s “hide” class.

*/ slider.prototype. process = function () {var self = this; this.working = true; this.dom.next = $(this.dom.project[this.next]); this.dom.current.css('z-index', 30); self.dom.next.css('z-index', 20); // Hide current this.dom.current.addClass('hide'); setTimeout(function () { self.dom.current.css('z-index', 10); self.dom.next.css('z-index', 30); self.dom.current.removeClass('hide'); self.dom.current = self.dom.next; self.current = self.next; self.working = false; }, this.durations.slide); };Copy the code

Adding the corresponding class triggers our animations, which in turn apply the mask image to our slideshows. The main idea is to create a transition flow by moving masks with a step animation function.

That’s all for this article! I hope you found this tutorial useful and enjoy it as you create your own cool mask effects! Don’t hesitate to share your creations and I’ll be happy to see!

Browser support:

  • Chrome support
  • Firefox does not support
  • Not supported by Internet Explorer
  • Safari support
  • Opera support

Reference and credit

See demo download source code