2

Sorry for the possible duplication, but I did not find a solution to my problem. About my problem. I am trying to create a slide carousel using only js and css. What I need is an alternation of slides when we press the “forward” or “back” buttons (for example, the previous slide goes off to the left, while the new slide simultaneously appears from the right when “forward” is pressing).

The code is here:

var slideIndex = 0;
var prev_slideIndex = slideIndex;

function myanimate() {
  str = 'slideIndex=' + slideIndex + ' prev_slideIndex=' + prev_slideIndex;

  var slides = document.getElementsByClassName("child");
  for (var i = 0; i < slides.length; i++) slides[i].style.display = "none";

  if (prev_slideIndex < slideIndex) {
    if (slideIndex > 3) slideIndex = 0;
    slides[prev_slideIndex].style.left = '-100%';
    slides[prev_slideIndex].style.marginleft = '0%';
    slides[slideIndex].style.left = '0%';
    slides[slideIndex].style.marginleft = '0%';
    slides[prev_slideIndex].style.animation = slides[slideIndex].style.animation = 'caroussel 1.5s';
  } else {
    if (slideIndex < 0) slideIndex = 3;
    slides[prev_slideIndex].style.left = '100%';
    slides[prev_slideIndex].style.marginleft = '0%';
    slides[slideIndex].style.left = '0%';
    slides[slideIndex].style.marginleft = '0%';
    slides[prev_slideIndex].style.animation = slides[slideIndex].style.animation = 'caroussel_back 1.5s';
  }

  slides[prev_slideIndex].style.display = 'block';
  slides[slideIndex].style.display = 'block';
  prev_slideIndex = slideIndex;

  str += ' final prev_slideIndex=' + prev_slideIndex;
  document.getElementById("text").innerHTML = str;
}
.parent {
  background-color: red;
  display: block;
  position: relative;
  width: 600px;
  height: 100px;
  padding-top: 10px;
  padding-bottom: 10px;
  overflow: hidden;
}

.child {
  background-color: green;
  display: block;
  position: absolute;
  width: 100%;
  height: 100px;
  color: #FFFFFF;
  font-size: 24px;
  text-align: center;
}

@keyframes caroussel {
  from {
    margin-left: 100%
  }
  to {
    margin-left: 0%
  }
}

@keyframes caroussel_back {
  0% {
    margin-left: -100%
  }
  100% {
    margin-left: 0%
  }
}
<input type="submit" value='forward' title="sdg" onclick="slideIndex++;myanimate();">
<input type="submit" value='backward' title="sdg" onclick="slideIndex--;myanimate();">
<br>
<div class="parent">
  <div class="child" style="background-color:yellow;left:0%;">
    Caption1<br>Caption1 Caption1 Caption1 Caption Caption Caption Caption Caption Caption
  </div>
  <div class="child" style="left:100%;">
    Caption2<br>Caption2 Caption2 Caption2 Caption2 Caption Caption Caption Caption Caption
  </div>
  <div class="child" style="background-color:magenta;left:100%;">
    Caption3<br>Caption3 Caption3 Caption3 Caption3 Caption Caption Caption Caption Caption
  </div>
  <div class="child" style="background-color:cyan;left:100%;">
    Caption4<br>Caption4 Caption4 Caption4 Caption4 Caption Caption Caption Caption Caption
  </div>
</div>
<br>
<span id="text"></span>

It works correctly if we press the “forward” and “back” buttons alternately (we can observe two slides), but it works incorrectly if we press one of these buttons several times (the previous slide disappears).

Does anyone know why it doesn’t work correctly or maybe there are any ideas how to improve the code?

Thank you in advance.

I tested in Firefox 74.0 (32bit). 'transform: translateX(...)' in css gives me the same behavior.

Gleb Kemarsky
  • 10,160
  • 7
  • 43
  • 68
Alexander Korovin
  • 1,639
  • 1
  • 12
  • 19
  • Please check this fiddle - https://jsfiddle.net/mightyteja/6a8gm7tu/10/ – mightyteja Apr 02 '20 at 15:16
  • Dear mightyteja thank you for the answer. Unfortunately, the carousel in you jsfiddle does not work (no slide turning), at least for me in firefox. – Alexander Korovin Apr 02 '20 at 15:23
  • I tested in firefox, I have added a click delay for the forward button(didn't add for backward), Also I added animation to control the carousel. Updated jsfiddle - https://jsfiddle.net/mightyteja/2eqnhmar/2/ – mightyteja Apr 02 '20 at 15:29
  • In my navigator, the slides are changed without animation when the "forward" button is pressed – Alexander Korovin Apr 02 '20 at 15:33

1 Answers1

1

The slide with the prev_slideIndex already got the same value for the animation on the previous iteration of the carousel. Therefore you need to use reflow to force this slide to play the same animation one more time:

slides[prev_slideIndex].offsetHeight; /* trigger reflow */

var slideIndex = 0;
var prev_slideIndex = slideIndex;

function myanimate() {
  str = 'slideIndex=' + slideIndex + ' prev_slideIndex=' + prev_slideIndex;

  var slides = document.getElementsByClassName("child");
  for (var i = 0; i < slides.length; i++) slides[i].style.display = "none";

  if (prev_slideIndex < slideIndex) {
    if (slideIndex > 3) slideIndex = 0;
    slides[prev_slideIndex].style.left = '-100%';
    slides[prev_slideIndex].style.marginleft = '0%';
    slides[slideIndex].style.left = '0%';
    slides[slideIndex].style.marginleft = '0%';
    slides[prev_slideIndex].offsetHeight; /* trigger reflow */
    slides[prev_slideIndex].style.animation = slides[slideIndex].style.animation = 'caroussel 1.5s';
  } else {
    if (slideIndex < 0) slideIndex = 3;
    slides[prev_slideIndex].style.left = '100%';
    slides[prev_slideIndex].style.marginleft = '0%';
    slides[slideIndex].style.left = '0%';
    slides[slideIndex].style.marginleft = '0%';
    slides[prev_slideIndex].offsetHeight; /* trigger reflow */
    slides[prev_slideIndex].style.animation = slides[slideIndex].style.animation = 'caroussel_back 1.5s';
  }

  slides[prev_slideIndex].style.display = 'block';
  slides[slideIndex].style.display = 'block';
  prev_slideIndex = slideIndex;

  str += ' final prev_slideIndex=' + prev_slideIndex;
  document.getElementById("text").innerHTML = str;
}
.parent {
  background-color: red;
  display: block;
  position: relative;
  width: 600px;
  height: 100px;
  padding-top: 10px;
  padding-bottom: 10px;
  overflow: hidden;
}

.child {
  background-color: green;
  display: block;
  position: absolute;
  width: 100%;
  height: 100px;
  color: #FFFFFF;
  font-size: 24px;
  text-align: center;
}

@keyframes caroussel {
  from {
    margin-left: 100%
  }
  to {
    margin-left: 0%
  }
}

@keyframes caroussel_back {
  0% {
    margin-left: -100%
  }
  100% {
    margin-left: 0%
  }
}
<input type="submit" value='forward' title="sdg" onclick="slideIndex++;myanimate();">
<input type="submit" value='backward' title="sdg" onclick="slideIndex--;myanimate();">
<br>
<div class="parent">
  <div class="child" style="background-color:yellow;left:0%;">
    Caption1<br>Caption1 Caption1 Caption1 Caption Caption Caption Caption Caption Caption
  </div>
  <div class="child" style="left:100%;">
    Caption2<br>Caption2 Caption2 Caption2 Caption2 Caption Caption Caption Caption Caption
  </div>
  <div class="child" style="background-color:magenta;left:100%;">
    Caption3<br>Caption3 Caption3 Caption3 Caption3 Caption Caption Caption Caption Caption
  </div>
  <div class="child" style="background-color:cyan;left:100%;">
    Caption4<br>Caption4 Caption4 Caption4 Caption4 Caption Caption Caption Caption Caption
  </div>
</div>
<br>
<span id="text"></span>
Gleb Kemarsky
  • 10,160
  • 7
  • 43
  • 68