Image Slider with clip-path animation

Cool slider animation with clip-path. Image slide show animation developed using CSS, HTML and JavaScript. Demo and Download options are available.

Demo Download

Author Uwe Chardon
Hits
Created SEPTEMBER 16, 2018
License Open
Compatible browsers Chrome, Firefox, Safari

HTML Snippet

 <div class="slider" data-state="0">  
      <svg id="prev" viewBox='0 0 100 100'>
        <circle cx="50" cy="50" r="85" />
        <path d="M 65,2 17,50 65,98" />
      </svg>
      <svg id="next" viewBox='0 0 100 100'>
        <circle cx="50" cy="50" r="85" />
        <path d="M 35,2 82,50 35,98" />
      </svg>
    
    <div class="status">
      <div class="stat" data-key="0"></div>
      <div class="stat" data-key="1"></div>
      <div class="stat" data-key="2"></div>
      <div class="stat" data-key="3"></div>
      <div class="stat" data-key="4"></div>
      <div class="stat" data-key="5"></div>
    </div>
    <div class="image" data-key="0" >
      <img src="https://picsum.photos/1200/1200/?image=111" alt=""/>
    </div>
    <div class="image" data-key="1">
      <img src="https://picsum.photos/1200/1200/?image=112" alt=""/>
    </div>
    <div class="image" data-key="2">
      <img src="https://picsum.photos/1200/1200/?image=116" alt=""/>
    </div>
    <div class="image" data-key="3">
      <img src="https://picsum.photos/1200/1200/?image=125" alt=""/>
    </div>
    <div class="image" data-key="4" data-active>
      <img src="https://picsum.photos/1200/1200/?image=122" alt=""/>
    </div>
    <div class="image" data-key="5">
      <img src="https://picsum.photos/1200/1200/?image=120" alt=""/>
    </div>
  </div>
<div class="dwf">done with fun - @uchardon</div>

CSS Code

@import url("https://fonts.googleapis.com/css?family=Roboto:400,400i,700");
html { 
  height: 100%; 
  background: #1A2A3A;  
  color: #FFF; 
}
body {
  font-family: Roboto, sans-serif;
  display:flex;
  justify-content:center;
  align-items: center;
}
*, *:before, *:after {
  box-sizing: border-box;
  position: relative;
  transition-property: clip-path, opacity;
  transition-duration: 900ms, 300ms;
  transition-timing-function: cubic-bezier(.5, 0, .5, 1);
}
.slider {
  position:relative;
  display: flex;
  width: 100vw;
  height: 90vh;
  overflow: hidden;
  .status {
    position: absolute;
    bottom: 10px;
    left:10px;
    display:flex;
    .stat {
      width:10px;
      height:10px;
      background-color:transparent;
      border-radius:50%;
      z-index:11;
      margin: 0px 5px;
      border: 2px solid #fff;
    }
    .stat[data-active] {
      background-color:#fff;
    }
  }
  
  img {
    object-fit: cover;
    object-position: center 80%;
    width: 100%;
    height: 100%;
    display: block;
  }
  .image {
    width: 100%;
    margin-right: -100%;
    opacity: 0;
    display: block;
    img {
      clip-path: circle(50px at 5vw 50%);
     }
  }
  .image[data-active] {
    opacity:1;
    img {
      clip-path: circle(100vmax at 50% 50%);
    }
  }
  .image[data-active] ~.image {
    opacity: 0;
    img{
      clip-path: circle(50px at 95vw 50%);
    }
  }
  svg {
   height: 30px;
    position:absolute;
    top:50%;
    margin-top:-15px;
    z-index: 1000;
    cursor: pointer;
    overflow:visible;
    path {
      stroke: #666;
      stroke-linecap:round;
      stroke-width:12px;
      fill:transparent;
    }
    circle {
      fill: #fff9;
    }
    &#next {
      right:5vw;

    }
    &#prev {
      left:5vw;
    }
  }
}
.dwf {
  position:fixed;
  bottom:4px;
  right:10px;
  background-color:#0003;
  padding:3px;
  border-radius:3px;
}

JavaScript Snippet

console.clear();
initslider();
function initslider() {
  const elPrevButton = document.querySelector('.slider #prev');
  const elNextButton = document.querySelector('.slider #next');

  const elImages = Array.from(document.querySelectorAll('.slider .image'));

  let state = {
    photo: 0
  };

  function send(event) {

    const elActives = document.querySelectorAll('.slider [data-active]');

    Array.from(elActives)
      .forEach(el => el.removeAttribute('data-active'));

    switch (event) {
      case 'PREV':
        state.photo--;
        // Math.max(state.photo - 1, 0);
        break;
      case 'NEXT':
        state.photo++;
        // Math.min(state.photo + 1, elImages.length - 1);
        break;
      default:
        state.photo = +event;
        break;
    }

    var len = elImages.length;
    // Loop Around
    //state.photo = ( ( state.photo % len) + len ) % len;
    state.photo = Math.max(0, Math.min( state.photo, len - 1) );

    Array.from(document.querySelectorAll(`.slider [data-key="${state.photo}"]`))
      .forEach( el => {
      el.setAttribute('data-active', true);
    });


  }
  elPrevButton.addEventListener('click', () => {
    send('PREV');
  });

  elNextButton.addEventListener('click', () => {
    send('NEXT');
  });

  const elStatus = Array.from(document.querySelectorAll('.slider .stat'));
  elStatus.forEach( stat => { 
    stat.addEventListener('click', () => {
      send(stat.dataset.key);
    });
  });
  send(0);
};

Preview

Image Slider with clip-path animation preview

Advertisement

Google Matched Content...