Search code examples
javascriptslidercarousel

Why does the Card slider loop through just the first 3 and not the remaining cards?


Im' trying to implement an idea from a Pen crated by Shamla on codepen at this link

I however noticed that the cards only cycle through the first 3 and does not progress to the fourth.

I know it likely in the javascript but cant figure out which part.

Id appreciate some help getting the card to loop all items.

thanks. please see code below.

$(document).ready(function() {
  let sliderItem = $(".slider").children(".item.active");
sliderItem.prev(".item").css({
  left: -200
});

sliderItem.next(".item").css({
  right: -200
});
let i = $(".slider").children(".item");
let ind = 0;
$(".slider")
  .children(".item")
  .each(function() {
    $(this).attr("data-index", ind++);
  });
i.on("click", function(e) {
  const that = $(this);
  let dataIndex = that.data("index");
  $(".item").removeClass("active");
  that.addClass("active");
  i.each(function() {
    if ($(this).data("index") == dataIndex) {
      $(this).addClass("active");
      $(this).css({
        left: 0,
        right: 0,
        "z-index": 3
      });
      if (dataIndex == "1") {
        $(".item[data-index=2]").css({
          left: 0,
          right: -200,
          "z-index": 1
        });
        $(".item[data-index=0]").css({
          left: -200,
          right: 0,
          "z-index": 1
        });
      } else if (dataIndex == "0") {
        $(".item[data-index=2]").css({
          left: -200,
          right: 0,
          "z-index": 1
        });
        $(".item[data-index=1]").css({
          left: 0,
          right: -200,
          "z-index": 1
        });
      } else if (dataIndex == "2") {
        $(".item[data-index=1]").css({
          left: -200,
          right: 0,
          "z-index": 1
        });
        $(".item[data-index=0]").css({
          left: 0,
          right: -200,
          "z-index": 1
        });
      }
    }
  });
});

});
body {
  background: #c0b5f5;
}

.slider {
  width: 75%;
  height: 80%;
  position: absolute;
  margin: 0 auto;
  left: 0;
  right: 0;
  top: 50px;
}
.slider .item {
  height: 100%;
  width: 100%;
  position: absolute;
  background: #fff;
  border-radius: 10px;
  transition: all ease 0.7s;
  z-index: 1;
  left: 0;
  opacity: 0.7;
  transform: scale(0.8);
  right: 0;
  margin: 0 auto;
}
.slider .item.active {
  z-index: 2;
  opacity: 1;
  background: #fff;
  transform: scale(1);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='slider'>
  <div class='item'>
    1
  </div>
  <div class='item active'>
    2
  </div>
  <div class='item'>
    3
  </div>
  <div class='item'>
    4
  </div>
  <div class='item'>
    5
  </div>
  <div class='item'>
    6
  </div>
</div>


Solution

  • It seems that you are overcomplicating your code. You are trying to set the style of each individual slide per active index. Doing this manually can be a hard and error prone task. I would suggest that you let CSS to the hard work for you.

    I'll introduce you to two selectors that you might not be familiar with yet, if you are skip this bit. The + (adjacent sibling selector) will select the direct element that comes after the plus sign. And the ~ (general sibling selector) will select all siblings after squiggly line. So for example.

    h1 + p{
      ...
    }
    

    This will select the p that comes directly after an h1 on the same level.

    h1 ~ p {
    
    }
    

    This will select all p that come after the h1 on the same level. With these selectors you can conditionally style your elements.

    So in your slider you want all the items that come before the active slide to be positioned to the left. So we set the CSS so every slide has a default position of to the left.

    .item {
      left: -200px;
      right: 0;
    }
    

    Now the .active slide has to be centered. So that slide is going to lose the left and right positions.

    .item.active {
      left: 0;
      right: 0;
    }
    

    And from here we are going to use the selectors. We want all the slides that come after the .active slide to move to the right. And we do that with the ~ selector.

    .item.active ~ .item {
      right: -200px;
      left: 0;
    }
    

    Now all your slides should be styled properly and don't require JS to move them to the correct position. As a finishing touch you would need to hide all the items that come after the item that is after the .active item. A mouthful, but check it out.

    .item.active + .item ~ .item {
      opacity: 0;
      visibility: hidden;
    }
    

    CSS is more powerful than you might think. I'd recommend that you only use JavaScript to manipulate CSS when you have make a calculation that cannot be done in CSS.

    Check out the snippet below to see it in action. Also consider using opaque background as your items will be overlapping. So a shade that emulates a transparency will do just as fine.

    Hope this helps you out. If I've been unclear or you have further questions, please let me know.

    Good luck!

    $(document).ready(function() {
    
      let $slider = $(".slider");
      let sliderItem = $slider.children(".item.active");
      let i = $slider.children(".item");
      let ind = 0;
      
      $slider
        .children(".item")
        .each(function() {
          $(this).attr("data-index", ind++);
        });
        
      i.on("click", function(e) {
        const that = $(this);
        let dataIndex = that.data("index");
        $(".item").removeClass("active");
        that.addClass("active");
      });
    
    });
    body {
      background: #c0b5f5;
    }
    
    .slider {
      width: 75%;
      height: 80%;
      position: absolute;
      margin: 0 auto;
      left: 0;
      right: 0;
      top: 50px;
    }
    
    .slider .item {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100%;
      width: 100%;
      position: absolute;
      background: #ede9ff;
      border-radius: 10px;
      transition: all ease 0.7s;
      z-index: 1;
      left: 0;
      transform: scale(0.8);
      left: -200px;
      right: 0;
      margin: 0 auto;
      
    }
    
    .slider .item.active {
      left: 0;
      right: 0;
      z-index: 2;
      opacity: 1;
      background: #fff;
      transform: scale(1);
    }
    
    .slider .item.active ~ .item {
      left: 0;
      right: -200px;
    }
    
    .slider .item.active + .item ~ .item {
      opacity: 0;
      visibility: hidden;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class='slider'>
      <div class='item'>
        1
      </div>
      <div class='item active'>
        2
      </div>
      <div class='item'>
        3
      </div>
      <div class='item'>
        4
      </div>
      <div class='item'>
        5
      </div>
      <div class='item'>
        6
      </div>
    </div>