CSS/JS slider using just data-attributes and transform:translate I needed to make a multi-page form, with slides, but without using too much js code like slick.js or the likes. So I tried to figure out how to make it really simple, but still cross-browser and responsive. I ended up with a small test using transform transitions. My question is: do you maybe see any relevant drawbacks on this technique?

The whole thing is based on 3 concepts:


If I use transforms, I'll not have scrollbars.
I can use data attributes to both track the current slide and style (move) the main strip with css
For this specific project, I can safely assume I won't never ever have more than 10 slides or so.


Notice that the demo slider does not loop. It's intentional, since for this specific project I don't want it to loop. Though, it would be fairly simple to make it loop, just change the current var accordingly.

Here is a link to the demo.

The code:

HTML

&lt;div class="main-box"&gt;

  &lt;div class="slide-box"&gt;&lt;!-- mask --&gt;
    &lt;div class="slides slides-7" data-current="1"&gt;&lt;!-- strip --&gt;
      &lt;div class="slide slide-1"&gt;1&lt;/div&gt;
      &lt;div class="slide slide-2"&gt;2&lt;/div&gt;
      &lt;div class="slide slide-3"&gt;3&lt;/div&gt;
      &lt;div class="slide slide-4"&gt;4&lt;/div&gt;
      &lt;div class="slide slide-5"&gt;5&lt;/div&gt;
      &lt;div class="slide slide-6"&gt;6&lt;/div&gt;
      &lt;div class="slide slide-7"&gt;7&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class="slide-buttons"&gt;
    &lt;button type="button" class="prev-button"&gt;prev&lt;/button&gt;
    &lt;button type="button" class="next-button"&gt;next&lt;/button&gt;
  &lt;/div&gt;

&lt;/div&gt;&lt;!-- /main-box --&gt;


CSS (scss)

.main-box{
  max-width: 600px;
  margin: 0 auto;
}

.slide-box{
  overflow:hidden;
}

.slides{
  background-color: #656565;
  display: flex;
  flex-wrap: nowrap;
  transition: transform 300ms;

  @for $i from 1 through 20{ // assuming slides won't never be &gt; 20
    &amp;[data-current="#{$i}"]{ transform: translateX(-100% * ($i - 1)); }
  }

  .slide{
    height: 300px;
    min-width: 100%;
    background-color: #ffb0b0;

    &amp;:nth-child(even){
      background-color: #ff8181;
    }
  }
}//slides


JS (jquery)

var slide_strip = $('.slides');
var slides = slide_strip.find('&gt; *');

var next_button = $('.next-button');
var prev_button = $('.prev-button');

next_button.on('click', function(e){ goto('next'); });
prev_button.on('click', function(e){ goto('prev'); });

function goto(direction){
  var current = parseInt(slide_strip.attr('data-current'), 10);

  if(direction == 'next'){
    if(current &gt;= slides.length) return;
    current++;
  } else {
    if(current &lt;= 1) return;
    current--;
  }

  slide_strip.attr('data-current', current);
}
My question is: do you maybe see any relevant drawbacks on this technique?


I don't see any drawbacks with the technique.

I do however see an improvement with the functions bound to the click handlers: 


next_button.on('click', function(e){ goto('next'); });
prev_button.on('click', function(e){ goto('prev'); });



These can be simplified using partially applied functions:

next_button.on('click', goto.bind(null, 'next'));
prev_button.on('click', goto.bind(null, 'prev'));


And since the else condition doesn't really check the value of direction you could cheat and just use goto as the bound function on the previous button click hander:

prev_button.on('click', goto);


Additionally, while it may utilize a few more function calls (thus being slightly slower) the code within goto() could be simplified using Math.min() and Math.max():

if(direction == 'next'){
    current = Math.min(slides.length, current + 1);
} else {
    current = Math.max(current - 1, 0); // zero-based
}




var slide_strip = $('.slides');
var slides = slide_strip.find('&gt; *');

var next_button = $('.next-button');
var prev_button = $('.prev-button');

next_button.on('click', goto.bind(null, 'next'));
prev_button.on('click',goto);

function goto(direction){
  var current = parseInt(slide_strip.attr('data-current'), 10);

  if(direction == 'next'){
    current = Math.min(slides.length, current + 1);
  } else {
    current = Math.max(current - 1, 0);
  }

  slide_strip.attr('data-current', current);
}
.main-box {
  max-width: 600px;
  margin: 0 auto;
}

.slide-box {
  overflow: hidden;
}

.slides {
  background-color: #656565;
  display: flex;
  flex-wrap: nowrap;
  transition: -webkit-transform 300ms;
  transition: transform 300ms;
  transition: transform 300ms, -webkit-transform 300ms;
}
.slides[data-current="1"] {
  -webkit-transform: translateX(0%);
          transform: translateX(0%);
}
.slides[data-current="2"] {
  -webkit-transform: translateX(-100%);
          transform: translateX(-100%);
}
.slides[data-current="3"] {
  -webkit-transform: translateX(-200%);
          transform: translateX(-200%);
}
.slides[data-current="4"] {
  -webkit-transform: translateX(-300%);
          transform: translateX(-300%);
}
.slides[data-current="5"] {
  -webkit-transform: translateX(-400%);
          transform: translateX(-400%);
}
.slides[data-current="6"] {
  -webkit-transform: translateX(-500%);
          transform: translateX(-500%);
}
.slides[data-current="7"] {
  -webkit-transform: translateX(-600%);
          transform: translateX(-600%);
}
.slides[data-current="8"] {
  -webkit-transform: translateX(-700%);
          transform: translateX(-700%);
}
.slides[data-current="9"] {
  -webkit-transform: translateX(-800%);
          transform: translateX(-800%);
}
.slides[data-current="10"] {
  -webkit-transform: translateX(-900%);
          transform: translateX(-900%);
}
.slides[data-current="11"] {
  -webkit-transform: translateX(-1000%);
          transform: translateX(-1000%);
}
.slides[data-current="12"] {
  -webkit-transform: translateX(-1100%);
          transform: translateX(-1100%);
}
.slides[data-current="13"] {
  -webkit-transform: translateX(-1200%);
          transform: translateX(-1200%);
}
.slides[data-current="14"] {
  -webkit-transform: translateX(-1300%);
          transform: translateX(-1300%);
}
.slides[data-current="15"] {
  -webkit-transform: translateX(-1400%);
          transform: translateX(-1400%);
}
.slides[data-current="16"] {
  -webkit-transform: translateX(-1500%);
          transform: translateX(-1500%);
}
.slides[data-current="17"] {
  -webkit-transform: translateX(-1600%);
          transform: translateX(-1600%);
}
.slides[data-current="18"] {
  -webkit-transform: translateX(-1700%);
          transform: translateX(-1700%);
}
.slides[data-current="19"] {
  -webkit-transform: translateX(-1800%);
          transform: translateX(-1800%);
}
.slides[data-current="20"] {
  -webkit-transform: translateX(-1900%);
          transform: translateX(-1900%);
}
.slides .slide {
  height: 300px;
  min-width: 100%;
  background-color: #ffb0b0;
}
.slides .slide:nth-child(even) {
  background-color: #ff8181;
}
&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;
&lt;div class="main-box"&gt;

      &lt;div class="slide-box"&gt;&lt;!-- mask --&gt;
        &lt;div class="slides slides-7" data-current="1"&gt;&lt;!-- strip --&gt;
          &lt;div class="slide slide-1"&gt;1&lt;/div&gt;
          &lt;div class="slide slide-2"&gt;2&lt;/div&gt;
          &lt;div class="slide slide-3"&gt;3&lt;/div&gt;
          &lt;div class="slide slide-4"&gt;4&lt;/div&gt;
          &lt;div class="slide slide-5"&gt;5&lt;/div&gt;
          &lt;div class="slide slide-6"&gt;6&lt;/div&gt;
          &lt;div class="slide slide-7"&gt;7&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="slide-buttons"&gt;
        &lt;button type="button" class="prev-button"&gt;prev&lt;/button&gt;
        &lt;button type="button" class="next-button"&gt;next&lt;/button&gt;
      &lt;/div&gt;

    &lt;/div&gt;&lt;!-- /main-box --&gt;