Home > Software design >  stacked cards carousel: looping z-index with jquery
stacked cards carousel: looping z-index with jquery

Time:07-28

I'm trying to create a carousel of stacked cards using CSS animations and Jquery. The DOM elements are the following:

<div >
  <div  style="background:orange;z-index:4">
    1
  </div>
  <div   style="background:tan;z-index:3">
    2
  </div>
  <div  style="background:pink;z-index:2">
    3
  </div>
   <div  style="background:blue;z-index:1">
    4
  </div>
</div>

what i need to to is having

  • the z-index:4 card to become z-index:1
  • the z-index:3 card to become z-index: 4
  • the z-index:2 card to become z-index: 3
  • the z-index:1 card to become z-index: 2

you get the point: the first card needs to be pushed back in the stack, the others should move "up" one level.

Here's a semi-working fiddle: https://jsfiddle.net/p34yzmhv/

I'm no JS expert, i really don't know how to loop the zindex value. I've been reading similar questions here on stackoverflow but couldn't find something exactly similar to my problem.

thanks any hint or help is greatly appreciated.

CodePudding user response:

You can put the z-index within a class and then change the class.

This also allows you to update the positions currently set with .card .card .card(etc) without which, your card1 would go to the back, but be position to be unseeable.

The alternative would be to move the elements in the DOM, which may or may not be simpler depending on what else you do with the cards.

Keeping with z4 = z-index=4 => positioned at the front (rather than more logical 1=at the front), add classes:

.z4 { 
  z-index: 4;
}
.z3 { 
  transform: rotate(2deg) translate3d(-50%, -50%, 0);
  z-index: 3; 
}
etc

Then, each iteration, remove all classes and add them back starting with the now current .active. .nextAll gives the following siblings while .prevAll gives the preceding siblings. Only .prevAll gives them in the reverse order so you also need to reverse that.

    $(".card").removeClass("z1 z2 z3 z4");
    let z=4;
    $(".card.active").addClass("z" z);
    $(".card.active").nextAll(".card").each((i, e) => { z--; $(e).addClass("z" z); });
    $($(".card.active").prevAll(".card").get().reverse()).each((i, e) => { z--; $(e).addClass("z" z); });
    
    // console.log to confirm they're in the correct order
    $(".card").each((i, e) => console.log(i, $(e).text(), e.className));

Updated snippet:

$(".btn2").click(function () {
  
  setTimeout(function () {
  
    var $next = $(".card.active").removeClass("active").next(".card");
    if ($next.length) {
      $next.addClass("active");
    } else {
      $(".card:first").addClass("active");
    }
    
    $(".card").removeClass("z1 z2 z3 z4");
    var z=4;
    $(".card.active").addClass("z" z);
    $(".card.active").nextAll(".card").each((i, e) => { z--; $(e).addClass("z" z); });
    $($(".card.active").prevAll(".card").get().reverse()).each((i, e) => { z--; $(e).addClass("z" z); });
    
    $(".card").each((i, e) => console.log(i, $(e).text(), e.className));

  }, 1);
  
  $(".card.active")
    .addClass("animation")
    .one(
      "animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd",
      function () {        
        $(".card").removeClass("animation");
      }
    );
});
@keyframes animation {
  0% {
    transform: rotate(0) translate3d(-50%, -50%, 0) scale(1);
    opacity: 1;
    z-index: 10;
  }
  15% {
    opacity: 1;
    z-index: 10;
    transform: rotate(2deg) translate3d(-50%, -50%, 0) scale(1.1);
  }
  50% {
    transform: rotate(-40deg) translate3d(-320%, -50%, 0) scale(0.1);
    opacity: 0;
    z-index: 0;
  }
  75% {
    opacity: 1;
  }
  100% {
    transform: rotate(0) translate3d(-50%, -50%, 0) scale(1);
    opacity: 1;
    z-index: 0;
  }
}

.animation {
  animation: animation 1s forwards cubic-bezier(0.83, 0, 0.17, 1);
}
.card {
  transform-origin: center;
  transform: rotate(0) translate3d(-50%, -50%, 0);
  transition: all 1s cubic-bezier(0.22, 1, 0.36, 1);

  &.active {
    transform: rotate(0) translate3d(-50%, -50%, 0)!important;
  }
}

// --------------------------------------------
// --------------- DEMO STYLES ----------------
// --------------------------------------------

html {
  height: 100%;
}
body {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  * {
    box-sizing: inherit;
  }
}

.btn2 {
  position: fixed;
  left: 50%;
  bottom: 10%;
  transform: translateX(-50%) translateY(-50%);
  background: coral;
  cursor: pointer;
  color: white;
  padding: 24px;
  text-transform: uppercase;
  z-index: 50;
  zoom: 1.2;
}

.container {
  width: 420px;
  height: 480px;
  background: #eee;
  overflow: hidden;
  margin: 0 auto;
  position: relative;
  padding: 20px;
}

.card {
  border-radius: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 400px;
  max-width: 320px;
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  &.active {
    box-shadow: 0 0 20px rgba(black, 0.25);
    border: 1px solid black;
  }
}


.z4 { 
  z-index: 4;
}
.z3 { 
  transform: rotate(2deg) translate3d(-50%, -50%, 0);
  z-index: 3; 
}
.z2 {
  transform: rotate(4deg) translate3d(-50%, -50%, 0);
  z-index: 2; 
}
.z1 { 
  transform: rotate(6deg) translate3d(-50%, -50%, 0);
  z-index: 1; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
  <div  style="background:orange">1</div>
  <div   style="background:tan">2</div>
  <div  style="background:pink">3</div>
   <div  style="background:blue">4</div>
</div>

<div >
  animate
</div>

Updated fiddle: https://jsfiddle.net/7z39mqdt/

  • Related