Last week we’ve been experimenting with SVG paths to animate the content of a full-page hero slider. Today we use the same technique to create a responsive carousel. This time, though, we used SVG paths to directly clip the slide images, with no need to show an intermediate layer.
Images: Unsplash
👋 A new version of this component is available. Download now →.
Creating the structure
The HTML structure is composed by an unordered list (ul.cd-slider
), containing the slides, and two additional list elements ( ul.cd-slider-navigation
and ol.cd-slider-controls
) for the slider navigations.
Each list item inside the ul.cd-slider
is composed by an svg containing a <clipPath>
element (used to change the clipping area of the slide image) and an <image>
element (whose clip-path url attribute is the <clipPath>
id).
<div class="cd-slider-wrapper">
<ul class="cd-slider" data-step1="M1402,800h-2V0.6c0-0.3,0-0.3,0-0.6h2v294V800z" data-step2="M1400,800H383L770.7,0.6c0.2-0.3,0.5-0.6,0.9-0.6H1400v294V800z" data-step3="M1400,800H0V0.6C0,0.4,0,0.3,0,0h1400v294V800z" data-step4="M-2,800h2L0,0.6C0,0.3,0,0.3,0,0l-2,0v294V800z" data-step5="M0,800h1017L629.3,0.6c-0.2-0.3-0.5-0.6-0.9-0.6L0,0l0,294L0,800z" data-step6="M0,800h1400V0.6c0-0.2,0-0.3,0-0.6L0,0l0,294L0,800z">
<li class="visible">
<div class="cd-svg-wrapper">
<svg viewBox="0 0 1400 800">
<title>Aimated SVG</title>
<defs>
<clipPath id="cd-image-1">
<path id="cd-changing-path-1" d="M1400,800H0V0.6C0,0.4,0,0.3,0,0h1400v294V800z"/>
</clipPath>
</defs>
<image height='800px' width="1400px" clip-path="url(#cd-image-1)" xlink:href="img/img-1.jpg"></image>
</svg>
</div> <!-- .cd-svg-wrapper -->
</li>
<li>
<div class="cd-svg-wrapper">
<svg viewBox="0 0 1400 800">
<!-- svg content here -->
</svg>
</div> <!-- .cd-svg-wrapper -->
</li>
<!-- other list items here -->
</ul> <!-- .cd-slider -->
<ul class="cd-slider-navigation">
<li><a href="#0" class="next-slide">Next</a></li>
<li><a href="#0" class="prev-slide">Prev</a></li>
</ul> <!-- .cd-slider-navigation -->
<ol class="cd-slider-controls">
<li class="selected"><a href="#0"><em>Item 1</em></a></li>
<li><a href="#0"><em>Item 2</em></a></li>
<!-- other list items here -->
</ol> <!-- .cd-slider-controls -->
</div> <!-- .cd-slider-wrapper -->
Adding style
The slider structure is quite basic: all slides have an opacity: 0, are in absolute position and are placed one on top of the other (top: 0 and left:0). The .visible
class is added to the selected slide (at the end of the clipping animation) to make it visible, while the .is-animating
class is added to the list item during the clipping animation (z-index: 3 so that it is over the li.visible
item).
Note: we had to use the Padding Hack to make the svg responsive (IE assumes svg height to be 150px if you don't explicitly define it). Basically, we set the div.cd-svg-wrapper
height to 0 and its padding-bottom to 57.15% (to preserve svg proportion, in our case 800/1400), and set the svg height and width to 100%.
.cd-slider > li {
position: absolute;
top: 0;
left: 0;
width: 100%;
opacity: 0;
}
.cd-slider > li.visible {
position: relative;
z-index: 2;
opacity: 1;
}
.cd-slider > li.is-animating {
z-index: 3;
opacity: 1;
}
.cd-slider .cd-svg-wrapper {
/* using padding Hack to fix bug on IE - svg height not properly calculated */
height: 0;
padding-bottom: 57.15%;
}
.cd-slider svg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
Events handling
To animate the slide image clipping area, we animated the 'd'
attribute of the <path>
element inside the <clipPath>
.
First of all, we had to define the different steps of our animation: we used the same process described in the Animated SVG Hero Slider article (Events handling section); but in this case, we needed only 6 steps (3 steps to animate from a slide to the next one and 3 more steps to animate from a slide to the previous one).
Once defined the paths, we added to the .cd-slider
a data-stepn
attribute (one for each step) equal to the 'd'
attribute of the defined path (to easily retrieve it with JavaScript).
We then used the animate()
method provided by Snap.svg to animate the path element.
clipPath.attr('d', path1).animate({'d': path2}, duration, firstCustomMinaAnimation, function(){
clipPath.animate({'d': path3}, duration, secondCustomMinaAnimation, function(){
oldSlide.removeClass('visible');
newSlide.addClass('visible').removeClass('is-animating');
});
});
Besides, we implemented a basic slider for the image gallery (with keyboard and touch swipe navigation, previous/next and dots navigation).