Optimus
Optimus

Reputation: 93

Create slider like infinite scrolling with CSS

I am trying to create CSS slider infinite scroll, but without appending/adding/creating DOM elements. Infinite scroll as in when the last slide is reached, the first slide should be shown again after it.

I have a fixed width slide, so the use of slick and box slider plugin does not work for me.

.slider-wrap {
  white-space: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  border: 1px solid red;
}

.slider-wrap .slide {
  display: inline-block;
  width: 200px;
  margin: 5px;
}

.slider-wrap .slide img {
  width: 100%;
}
<div class="slider-wrap">

  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>
  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>
  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>
  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>
  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>
  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>
  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>

</div>

Upvotes: 0

Views: 3305

Answers (1)

Ivan
Ivan

Reputation: 40668

Here are two options:

  • clone the items: you get a more natural approach (cloning isn't that bad). That's the system you would usually find on websites to add more content.

  • revert the position scroll position to another position to make it seem the slider never ends. Beware this will not make the scroll bar smaller as the content of the slider never gets changed


(a) Cloning

As you said you can clone the images.

The trick is to determine when the scroll has reached the end of the slider to clone more images in:

$(function() {
  $('.slider-wrap').scroll(function() {
    
    const slider = $(this);
          width = slider.innerWidth()
          scrollWidth = slider[0].scrollWidth;
          scrollLeft = slider.scrollLeft();
    
    if(scrollWidth - width == scrollLeft) {
      slider.children().clone().appendTo(slider);
    }
    
  });
});
.slider-wrap {
  white-space: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  border: 1px solid red;
}

.slider-wrap .slide {
  display: inline-block;
  width: 200px;
  margin: 5px;
}

.slider-wrap .slide img {
  width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="slider-wrap">
  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>
  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>
  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>
  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>
  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>
  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>
  <div class="slide">
    <img src="http://via.placeholder.com/350x150">
  </div>

</div>


And here's a demo:

$(function(){$('.slider-wrap').scroll(function(){const slider=$(this);var $width=slider.innerWidth()
var $scrollWidth=slider[0].scrollWidth;var $scrollLeft=slider.scrollLeft();if($scrollWidth-$width==$scrollLeft){slider.children().clone().appendTo(slider)}})})
.slider-wrap{white-space:nowrap;overflow-x:auto;overflow-y:hidden;border:1px solid red}.slider-wrap .slide{display:inline-block;margin:5px}.slider-wrap .slide img{height:120px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div class="slider-wrap"> <div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTa4e2VF6cfou9oL0cc5OAzVTEbmAgFjIW2r-7lTkpOljG9k38N"> </div><div class="slide"> <img src="https://nbocdn.akamaized.net/Assets/Images_Upload/2018/01/06/0060bbce-f2f2-11e7-bf60-029def90d6d6_web_scale_0.0542636_0.0542636__.jpg?maxheight=460&maxwidth=638&scale=both"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQr0xQ-gVF1Sy1a1sHoUyfGdrBwyz-5u0Tirkt-uNCKd-AzNXY1ww"> </div><div class="slide"> <img src="https://cdn.pixabay.com/photo/2017/05/29/15/34/kitten-2354016_960_720.jpg"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTJLwVbVu6tjubsduR43je-Muk7p8lAKDu569GuL_yDWGzrZwp2"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQRHeW6zNDdDQBwtpuu3RvLW1ihM3Za-OLBoOMRR_4z7GvwYor2eQ"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRKeCmurlUrTtd4CjvXYskGVAUAiDq5X49iNb3XhOcMss2vN8c6"> </div></div>


(b) A hack with scrollLeft

You could also go straight back to the first slide container by setting the scrollLeft to the position when it first added a new slide container:

let firstPos = undefined;

$('.slider').scroll(function() {

  const slider = $(this);
        width = slider.innerWidth()
        scrollWidth = slider[0].scrollWidth;
        scrollLeft = slider.scrollLeft();
        isEndOfSlider = (scrollWidth - width) == scrollLeft;
        numberOfWraps = slider.children().length;


  if(isEndOfSlider) {    
    
    if(numberOfWraps == 1) {

      firstPos = scrollLeft;
      slider.children().first().clone().appendTo(slider);

    } else {

      slider.scrollLeft(firstPos);

    }      

  }


});
.slider {
  white-space: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  border: 1px solid red;
}

.slider-wrap {
  display: inline-block;
}

.slider-wrap .slide {
  display: inline-block;
  width: 200px;
  margin: 5px;
}

.slider-wrap .slide img {
  width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="slider">
  <div class="slider-wrap">
    <div class="slide">1
      <img src="http://via.placeholder.com/350x150">
    </div>
    <div class="slide">2
      <img src="http://via.placeholder.com/350x150">
    </div>
    <div class="slide">3
      <img src="http://via.placeholder.com/350x150">
    </div>
    <div class="slide">...
      <img src="http://via.placeholder.com/350x150">
    </div>
    <div class="slide">...
      <img src="http://via.placeholder.com/350x150">
    </div>
    <div class="slide">-2
      <img src="http://via.placeholder.com/350x150">
    </div>
    <div class="slide">-1
      <img src="http://via.placeholder.com/350x150">
    </div>
  </div>
</div>


Here's a demo:

let firstPos=undefined;$('.slider').scroll(function(){const slider=$(this);width=slider.innerWidth()
scrollWidth=slider[0].scrollWidth;scrollLeft=slider.scrollLeft();isEndOfSlider=(scrollWidth-width)==scrollLeft;numberOfWraps=slider.children().length;if(isEndOfSlider){if(numberOfWraps==1){firstPos=scrollLeft;slider.children().first().clone().appendTo(slider)}else{slider.scrollLeft(firstPos)}}})
.slider{white-space:nowrap;overflow-x:auto;overflow-y:hidden;border:1px solid red}.slider-wrap{display:inline-block}.slider-wrap .slide{display:inline-block;margin:5px}.slider-wrap .slide img{width:auto;height:120px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div class="slider"> <div class="slider-wrap"> <div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTa4e2VF6cfou9oL0cc5OAzVTEbmAgFjIW2r-7lTkpOljG9k38N"> </div><div class="slide"> <img src="https://nbocdn.akamaized.net/Assets/Images_Upload/2018/01/06/0060bbce-f2f2-11e7-bf60-029def90d6d6_web_scale_0.0542636_0.0542636__.jpg?maxheight=460&maxwidth=638&scale=both"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQr0xQ-gVF1Sy1a1sHoUyfGdrBwyz-5u0Tirkt-uNCKd-AzNXY1ww"> </div><div class="slide"> <img src="https://cdn.pixabay.com/photo/2017/05/29/15/34/kitten-2354016_960_720.jpg"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTJLwVbVu6tjubsduR43je-Muk7p8lAKDu569GuL_yDWGzrZwp2"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQRHeW6zNDdDQBwtpuu3RvLW1ihM3Za-OLBoOMRR_4z7GvwYor2eQ"> </div><div class="slide"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRKeCmurlUrTtd4CjvXYskGVAUAiDq5X49iNb3XhOcMss2vN8c6"> </div></div></div>

Upvotes: 5

Related Questions