CSS/JS slider using just data-attributes and transform:translate

Posted on

Problem

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

<div class="main-box">

  <div class="slide-box"><!-- mask -->
    <div class="slides slides-7" data-current="1"><!-- strip -->
      <div class="slide slide-1">1</div>
      <div class="slide slide-2">2</div>
      <div class="slide slide-3">3</div>
      <div class="slide slide-4">4</div>
      <div class="slide slide-5">5</div>
      <div class="slide slide-6">6</div>
      <div class="slide slide-7">7</div>
    </div>
  </div>

  <div class="slide-buttons">
    <button type="button" class="prev-button">prev</button>
    <button type="button" class="next-button">next</button>
  </div>

</div><!-- /main-box -->

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 > 20
    &[data-current="#{$i}"]{ transform: translateX(-100% * ($i - 1)); }
  }

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

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

JS (jquery)

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

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 >= slides.length) return;
    current++;
  } else {
    if(current <= 1) return;
    current--;
  }

  slide_strip.attr('data-current', current);
}

Solution

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
}

Leave a Reply

Your email address will not be published. Required fields are marked *