Clipped SVG Slider

Clipped SVG Slider

A simple slider, with morphing preview images animated using SVG properties.

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

Here on CodyHouse we’ve published a lot of SVG experiments! What’s really powerful with SVG is the possibility to combine path animations with the clipPath element. Add a touch of CSS transformations and you got a spicy recipe!

Inspiration: Music player animation by Veronika Lykova.

Tool used: Snap.svg

Images: Unsplash

Creating the structure

The HTML structure is composed of three unordered lists: a ul.gallery  and a ul.navigation for the slider images and navigation, and a ul.caption for the image captions.

Each list item inside the ul.gallery is composed of a .svg-wrapper element wrapping a <svg> containing a  <clipPath> element (used to change the clipping area of the slide image), an <image> element (whose clip-path url attribute is the<clipPath> id), and a <use> element (whose xlink:href attribute is the<clipPath> id) used to create the layer covering the slide images not in the center.

<div class="cd-svg-clipped-slider" data-selected="M780,0H20C8.954,0,0,8.954,0,20v760c0,11.046,8.954,20,20,20h760c11.046,0,20-8.954,20-20V20 C800,8.954,791.046,0,780,0z" data-lateral="M795.796,389.851L410.149,4.204c-5.605-5.605-14.692-5.605-20.297,0L4.204,389.851 c-5.605,5.605-5.605,14.692,0,20.297l385.648,385.648c5.605,5.605,14.692,5.605,20.297,0l385.648-385.648 C801.401,404.544,801.401,395.456,795.796,389.851z">
   <div class="gallery-wrapper">
      <ul class="gallery">
         <li class="left">
            <div class="svg-wrapper">
               <svg viewBox="0 0 800 800">
                  <title>Animated SVG</title>
                  <defs>
                     <clipPath id="cd-image-1">
                        <path id="cd-morphing-path-1" d="M795.796,389.851L410.149,4.204c-5.605-5.605-14.692-5.605-20.297,0L4.204,389.851 c-5.605,5.605-5.605,14.692,0,20.297l385.648,385.648c5.605,5.605,14.692,5.605,20.297,0l385.648-385.648 C801.401,404.544,801.401,395.456,795.796,389.851z"/>
                     </clipPath>
                  </defs>

                  <image height='800px' width="800px" clip-path="url(#cd-image-1)" xlink:href="img/img-01.jpg"></image>
                  <use xlink:href="#cd-morphing-path-1" class="cover-layer" />
               </svg>
            </div> <!-- .svg-wrapper -->
         </li>

         <li class="selected">
            <div class="svg-wrapper">
               <svg viewBox="0 0 800 800">
                  <title>Animated SVG</title>
                  <defs>
                     <clipPath id="cd-image-2">
                        <path id="cd-morphing-path-2" d="M780,0H20C8.954,0,0,8.954,0,20v760c0,11.046,8.954,20,20,20h760c11.046,0,20-8.954,20-20V20 C800,8.954,791.046,0,780,0z"/>
                     </clipPath>
                  </defs>
            
                  <image height='800px' width="800px" clip-path="url(#cd-image-2)" xlink:href="img/img-02.jpg"></image>
                  <use xlink:href="#cd-morphing-path-2" class="cover-layer" />
               </svg>
            </div> <!-- .svg-wrapper -->
         </li>

         <!-- other slides here -->
      </ul>

      <nav>
         <ul class="navigation">
            <li><a href="#0" class="prev">Prev</a></li>
            <li><a href="#0" class="next">Next</a></li>
         </ul>
      </nav>
   </div>

   <ul class="caption">
      <li class="left">Lorem ipsum dolor</li>
      <li class="selected">Consectetur adipisicing elit</li>
      <!-- other captions here -->
   </ul>
</div> <!-- .cd-svg-clipped-slider -->

Adding style

By default, all the list items inside the ul.gallery have a position absolute, an opacity of zero and are moved to the right and scaled down.

.cd-svg-clipped-slider .gallery li {
  /* slider images */
  position: absolute;
  z-index: 1;
  top: 0;
  left: 25%;/* (100% - width)/2 */
  width: 50%;
  height: 100%;
  opacity: 0;
  transform: translateX(75%) scale(0.4);
  transition: opacity .3s, transform .3s ease-in-out;
}

The .selected class is then used to move the selected image back to the center and to scale it up.

.cd-svg-clipped-slider .gallery li.selected {
  /* slide in the center */
  position: relative;
  z-index: 3;
  opacity: 1;
  transform: translateX(0) scale(1);
}

The .left and .right classes are used to show the preview images on both sides of the selected image; the .left class is also used to move an image preview to the left.

.cd-svg-clipped-slider .gallery li.left {
  /* slides on the left */
  transform: translateX(-75%) scale(0.4);
}
.cd-svg-clipped-slider .gallery li.left, 
.cd-svg-clipped-slider .gallery li.right {
  /* .right -> slide visible on the right */
  z-index: 2;
  opacity: 1;
}

When a new slide is selected, the <path> element used to clip the slide image is animated to reveal a different portion of the image (the entire image if the slide is the .selected one, or just a section for the .left/.right images).

The same classes are also used to control the visibility/position of the image captions. By default, all captions are hidden and moved to the right; the class .selected is used to show the selected caption and move it back to the center, while the .left class is used to hide it and move it to the left.

.cd-svg-clipped-slider .caption li {
  /* slide titles */
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  text-align: center;
  width: 100%;
  transform: translateX(100px);
  opacity: 0;
  transition: opacity .3s, transform .3s ease-in-out;
}
.cd-svg-clipped-slider .caption li.selected {
  /* slide visible in the center */
  z-index: 2;
  position: relative;
  transform: translateX(0);
  opacity: 1;
}
.cd-svg-clipped-slider .caption li.left {
  /* slide hidden on the left */
  transform: translateX(-100px);
}

Events handling

To implement this slider we created a svgClippedSlider object and used the bindEvents method to attach event handlers for the click to the slider navigation.

function svgClippedSlider(element) {
   this.element = element;
   this.slidesGallery = this.element.find('.gallery').children('li');
   this.slidesCaption = this.element.find('.caption').children('li');
   this.slidesNumber = this.slidesGallery.length;
   this.selectedSlide = this.slidesGallery.filter('.selected').index();
   // ....

   this.bindEvents();
}

svgClippedSlider.prototype.bindEvents = function() {
   var self = this;
   //detect click on one of the slides
   this.slidesGallery.on('click', function(event){
      if( !$(this).hasClass('selected') ) {
         //determine new slide index and show it
         var newSlideIndex = ( $(this).hasClass('left') )
            ? self.showPrevSlide(self.selectedSlide - 1)
            : self.showNextSlide(self.selectedSlide + 1);
      }
   });
}

The showPrevSlide and showNextSlide methods take care of showing the selected slide; these functions are used to add/remove the proper classes from the slide images and captions, and to animate the 'd' attribute of the <path> element inside the <clipPath> used to clip the slide image.

Join our newsletter

Get our monthly recap with the latest CodyHouse news