2
\$\begingroup\$

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);
}
\$\endgroup\$
2
\$\begingroup\$

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('> *');

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;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<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 -->

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.