21

I've got a slider set up using slick slider. When using the next and previous buttons, the item comes in to view with a nice transition. The problem I'm having is that when it restarts its cycle, the first item "snaps" into view, instead of doing the transition. Furthermore it seems like it loses it's internal indexing, as the css "odd" and "even" classes are changed. See snippet below:

$(document).ready(function() {
    $('.items').slick({
        slidesToShow: 2,
        speed: 500
    });
});
* {
  margin: 0;
  padding: 0;
}

ul {
  list-style: none;
  height: 150px;
}

.slick-list, .slick-track {
  height: 100%;
}

ul li {
  width: 350px;
  height: 100%;
}

ul li .content {
  width: 100%;
  height: 100%;
  transition: transform 0.5s linear;
  text-align: center;
}

ul li .content span {
  color: #fff;
  font-size: 50px;
  font-family: Arial;
  position: relative;
  top: 50%;
  transform: translateY(-50%);
  display: block;
}

ul li:nth-child(odd) .content {
  background-color: red;
}

ul li:nth-child(even) .content {
  background-color: green;
}

ul li:not(.slick-current) .content {
  transform: scale(0.9);
}
<link href="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js"></script>
<ul class="items">
  <li class="item">
    <div class="content">
      <span>1</span>
    </div>
  </li>

  <li class="item">
    <div class="content">
      <span>2</span>
    </div>
  </li>

  <li class="item">
    <div class="content">
      <span>3</span>
    </div>
  </li>

  <li class="item">
    <div class="content">
      <span>4</span>
    </div>
  </li>

  <li class="item">
    <div class="content">
      <span>5</span>
    </div>
  </li>
</ul>

I think I know why it's doing this, it's because it has to create "cloned" items for the infinite loop functionality to work. I've tried a few different slider plugins and they all seem to have similar issues.

Does anyone know how I can fix this? jsfiddle here: https://jsfiddle.net/7kdmwkd9/1/

Jennifer Goncalves
  • 1,442
  • 1
  • 12
  • 29
MAX POWER
  • 5,213
  • 15
  • 89
  • 141
  • 1
    The [Flickity](https://flickity.metafizzy.co/) slider does not seem to have the "snapping" problem. As for the odd/even styling problem, you could do this: if you have an odd number of items, duplicate the list. See [this jsfiddle](https://jsfiddle.net/ConnorsFan/vm9nn5e0/5/). – ConnorsFan Aug 02 '17 at 04:33
  • Looks good that, I'll give it a try! – MAX POWER Aug 02 '17 at 09:42

10 Answers10

25

Solution 1 - Use Flickity

If you want to try another carousel control, you can have a look at Flickity. According to my tests with the wrapAround option, it does not "snap" the first item back into position when the full cycle is complete; the transition goes on smoothly. You can see it at work in this jsfiddle.

As for the problem with formatting the items according to their even/odd index, it happens only when you have an odd number of items. One solution would be to duplicate the list of items. Intead of

Item 1 / Item 2 / Item 3 / Item 4 / Item 5

you could define

Item 1 / Item 2 / Item 3 / Item 4 / Item 5 / Item 1 / Item 2 / Item 3 / Item 4 / Item 5

That would ensure that you work with an even number of items.


Solution 2 - Slick Slider: add transition delay

With Slick Slider, adding a delay to the transition helps to make it smoother when the cycle completes. In the code snippet below, I replaced:

ul li .content {
  transition: transform 0.5s linear;
  ...
}

ul li:not(.slick-current) .content {
  transform: scale(0.9);
}

with

ul li .content {
  transition: transform 0.3s linear;
  transition-delay: 0.5s;
  ...
}

ul li:not(.slick-current) .content {
  transform: scale(0.9);
  transition-delay: 0s;
}

$(document).ready(function() {
  $('.items').slick({
    infinite: true,
    speed: 500,
    slidesToShow: 2,
    variableWidth: false
  });
});
* {
  margin: 0;
  padding: 0;
}

ul {
  list-style: none;
  height: 150px;
}

.slick-list,
.slick-track {
  height: 100%;
}

ul li {
  width: 350px;
  height: 100%;
}

ul li .content {
  width: 100%;
  height: 100%;
  transition: transform 0.3s linear;
  transition-delay: 0.5s;
  text-align: center;
}

ul li .content span {
  color: #fff;
  font-size: 50px;
  font-family: Arial;
  position: relative;
  top: 50%;
  transform: translateY(-50%);
  display: block;
}

ul li:nth-child(odd) .content {
  background-color: red;
}

ul li:nth-child(even) .content {
  background-color: green;
}

ul li:not(.slick-current) .content {
  transform: scale(0.9);
  transition-delay: 0s;
}
<link href="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js"></script>
<ul class="items">
  <li class="item">
    <div class="content">
      <span>1</span>
    </div>
  </li>
  <li class="item">
    <div class="content">
      <span>2</span>
    </div>
  </li>
  <li class="item">
    <div class="content">
      <span>3</span>
    </div>
  </li>
  <li class="item">
    <div class="content">
      <span>4</span>
    </div>
  </li>
  <li class="item">
    <div class="content">
      <span>5</span>
    </div>
  </li>
  <li class="item">
    <div class="content">
      <span>1</span>
    </div>
  </li>
  <li class="item">
    <div class="content">
      <span>2</span>
    </div>
  </li>
  <li class="item">
    <div class="content">
      <span>3</span>
    </div>
  </li>
  <li class="item">
    <div class="content">
      <span>4</span>
    </div>
  </li>
  <li class="item">
    <div class="content">
      <span>5</span>
    </div>
  </li>
</ul>
ConnorsFan
  • 70,558
  • 13
  • 122
  • 146
  • I modified my answer to give a solution for slick slider. – ConnorsFan Aug 04 '17 at 14:06
  • 1
    I used your solution for Flickity slider and that is what I have gone with. Thanks :) – MAX POWER Aug 04 '17 at 22:09
  • 2
    Great solution, Just adding `transition-delay` fixed the issue. Good to learn this. Vote up – Alex Mac Aug 05 '17 at 20:14
  • **2022** and this problem **still occurs**, thank you. Adding the transition, and inverting the design by targeting ALL the items and giving them the design we want on the current-active one and resetting the style for the items that *are not* the current-active one worked perfectly ! – maiakd Apr 21 '22 at 14:37
  • @maiakd would you please share an example? – petr Jul 05 '22 at 10:41
  • Thanks, this fixed a CLS issue for me – Lamellama Jan 03 '23 at 12:43
5

@GSTAR, Eventually there is no error in your code but there is bit css and js flow you need to understand while using slick.

Slick is cloning your slides and amend in top and down of your slide. like describe below.

Your Code before Slick implementation

<ul class="items">
    <li class="item"><div class="content"><span>1</span></div></li>
    <li class="item"><div class="content"><span>2</span></div></li>
    <li class="item"><div class="content"><span>3</span></div></li>
    <li class="item"><div class="content"><span>4</span></div></li>
    <li class="item"><div class="content"><span>5</span></div></li>
    <li class="item"><div class="content"><span>6</span></div></li>
</ul>

Your Code After Slick implementation

<ul class="items">
    <li class="item slick-cloned"><div class="content"><span>4</span></div></li>
    <li class="item slick-cloned"><div class="content"><span>5</span></div></li>
    <li class="item slick-cloned"><div class="content"><span>6</span></div></li>

    <li class="item"><div class="content"><span>1</span></div></li>
    <li class="item"><div class="content"><span>2</span></div></li>
    <li class="item"><div class="content"><span>3</span></div></li>
    <li class="item"><div class="content"><span>4</span></div></li>
    <li class="item"><div class="content"><span>5</span></div></li>
    <li class="item"><div class="content"><span>6</span></div></li>

    <li class="item slick-cloned"><div class="content"><span>1</span></div></li>
    <li class="item slick-cloned"><div class="content"><span>2</span></div></li>
    <li class="item slick-cloned"><div class="content"><span>3</span></div></li>
</ul>

Also after adding this your animation code is working fine. but it can not visually visible. if you increase this animation time than it will not snaps your browser.

If you replace javascript code than you will come to know what is happening.

<script type="text/javascript">
    $(document).ready(function() {
        $('.items').slick({
            centerMode:true,
            slidesToShow: 3,
            speed: 500,
            infinite: true,
            cssEase: 'linear',
            variableWidth: true
        });
    });
</script>

So after loop get finished and reaching to the first slide animation executed and before reach it get finished.

Please check below my snippet.

$(document).ready(function() {
    $('.items').slick({
        slidesToShow: 2,
        speed: 500
    });
});
* {
  margin: 0;
  padding: 0;
}

ul {
  list-style: none;
  height: 150px;
}

.slick-list, .slick-track {
  height: 100%;
}

ul li {
  width: 350px;
  height: 100%;
}

ul li .content {
  width: 100%;
  height: 100%;
  transition: transform 0.5s linear;
  transition-delay: 0.5s;
  text-align: center;
}

ul li .content span {
  color: #fff;
  font-size: 50px;
  font-family: Arial;
  position: relative;
  top: 50%;
  transform: translateY(-50%);
  display: block;
}

ul li:nth-child(odd) .content {
  background-color: red;
}

ul li:nth-child(even) .content {
  background-color: green;
}

ul li:not(.slick-current) .content {
  transform: scale(0.9);
}
<link href="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js"></script>
<ul class="items">
  <li class="item">
    <div class="content">
      <span>1</span>
    </div>
  </li>

  <li class="item">
    <div class="content">
      <span>2</span>
    </div>
  </li>

  <li class="item">
    <div class="content">
      <span>3</span>
    </div>
  </li>

  <li class="item">
    <div class="content">
      <span>4</span>
    </div>
  </li>

  <li class="item">
    <div class="content">
      <span>5</span>
    </div>
  </li>
  <li class="item">
    <div class="content">
      <span>6</span>
    </div>
  </li>
</ul>

In infinite loop you have user odd and even css so as per the loop it your next first slide(cloned slide) has green color but your original slide(first slide) has red color hence it flicking color also. If you use number of slides in %2, then this will not happen.

enter image description here

Hope it will help you to understand better.

Alex Mac
  • 2,970
  • 1
  • 22
  • 39
  • This solves the styling issue (in an admittedly clever way), however, the first slide still snaps into place, while you seem to claim you have solved it. – Patrick Roberts Aug 04 '17 at 14:12
  • @Patrick : Again read my answer, I mentioned that what's happening,I try to explain why it snaps. I never claimed that I solved it, I just gave another way to handle it. – Alex Mac Aug 04 '17 at 15:46
4

This is not an issue, it's a feature - this is just how slick slider (and most of other infinite-loop sliders) works. Basically, if slider would only clone divs it would end up with a huge performance issue, thus in certain places (beginning/end) after animation it rerender whole thing to start over.

If you are interested here is a proof-of-concept of slider that is based on transition and does not clone anything, just changes positions. Also maybe there is possibility to achieve the same with order - haven't tried but thought about it now.

https://codepen.io/prowseed/pen/QMEQxg - of course it requires a lot of work to make it fully usable, but I tried to make it responsive and the most similar to your example. You just have to keep track of index to add/remove certain classes (.current for example).

Maciej Kwas
  • 6,169
  • 2
  • 27
  • 51
2

Here my hack for slick.js Warning!! use its carefully, cause its alter source code of plugin

1) Find function
Slick.prototype.setSlideClasses and replace its definition from

 Slick.prototype.setSlideClasses = function(index) 

to

Slick.prototype.setSlideClasses = function(index, oldSlide)

2) in body of this function after code

_.$slides
    .eq(index)
    .addClass('slick-current');

add

if(oldSlide!=undefined){
    if(index==0 && oldSlide!=1){
        var _current = this.$slides.eq(this.$slides.size()-1);
        var __index = allSlides.index(_current);
        var ss = allSlides.eq(__index+1);
        ss.addClass('slick-current');
    }
    if(index==this.$slides.size()-1 && oldSlide!=this.$slides.size()-2){
        var _current = this.$slides.eq(0);
        var __index = allSlides.index(_current);
        var ss = allSlides.eq(__index-1);
        ss.addClass('slick-current');
    }
}

3) find function Slick.prototype.slideHandler in its body replace call

oldSlide = _.currentSlide;
_.currentSlide = animSlide;
_.setSlideClasses(_.currentSlide);

to

oldSlide = _.currentSlide;
_.currentSlide = animSlide;
_.setSlideClasses(_.currentSlide,oldSlide);
rudenich
  • 21
  • 1
  • 2
  • Would be awesome if this fixed it. Alas, it does not. – blerg Jun 13 '18 at 23:04
  • This works for going to next slide, but the glitch remains when going to prev slides. Can you patch this fix? Would be awesome to have both directions working! – Justin Breen May 18 '19 at 21:25
1

Infinity set to true, CenterMode set to false add effect to current just css

/* slide when not active*/ 
.slick-slide[aria-hidden="true"]:not(.slick-cloned) ~ .slick-cloned[aria-hidden="true"] {

}

/* slide when active (when play last to first) */ 
.slick-slide[aria-hidden="true"]:not([tabindex="-1"]) + .slick-cloned[aria-hidden="true"]  {

}
/* slide when active (when play first to last) */ 
.slick-slide[aria-hidden="true"] + .slick-cloned[aria-hidden="true"] {

}
Artur Bajak
  • 29
  • 2
  • 5
0

@Maciej Kwas

It might be a feature but on this site when you look on slider with "Center Mode" it works fine, the animation looks OK when sliding from last to first slide. http://kenwheeler.github.io/slick/

0

Since I have trouble letting go of the past, I'm still using Slick. I came across this issue and it turned out the problem was my slider images were using srcset attributes. Remove that fixed the issue.

Gavin
  • 7,544
  • 4
  • 52
  • 72
0

Applying transition on ".slick-center" class instead of ".slick-active" solved this issue for me

.slick-slide {
  transform: scale(0.85);
  pointer-events: none;
  transition: transform 0.6s linear;
}

.slick-center {
  transform: scale(1);
  pointer-events: all;
first
  • 616
  • 1
  • 7
  • 13
0

try to add animation within slick-center class and not slick-current

  • attach example so that get proper confirmation. – Savaj Patel Aug 18 '23 at 07:25
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 18 '23 at 07:25
-1

I found a really simple solution to my version of the issue, which was that once all 4 slides had completed it would loop back round aggressively / buggy.

I found that adding the following provided an infinite loop with no glitching

.slick-track {
transition: fade 2000ms ease-out;  
infinite: true;  
}