1

I've recently started work on a basic landing-page website. Part of the page is a basic image slider with both the auto-nav and the manual nav being powered by JS. I got everything working but for one thing: I just can't figure out how to get the smooth transition between images - as seen in this example - to work. I figured out the problem after reading some related questions on Stackoverflow: To make the Slideshow work I'm using slides[i].style.display = "none"; and slides[slideIndex-1].style.display = "block"; to update the css code handling the 'display' element - this over rights the 'transition: 2s' css code one would need for the simple slide animation as seen in the video. As I'm terribly new to Web development I could not wrap my head around possible solutions posted here on Stackoverflow and would really appreciate anyone that could help me out with an answer to my specific problem or an alternative way to solve it.

Cheers, Jerome

var slideIndex = 1;
showSlides(slideIndex);

// Next/previous controls
function plusSlides(n) {
  showSlides(slideIndex += n);
}

// Thumbnail image controls
function currentSlide(n) {
  showSlides(slideIndex = n);
}

function showSlides(n) {
  var i;
  var slides = document.getElementsByClassName("item");
  var dots = document.getElementsByClassName("dot");
  if (n > slides.length) {
    slideIndex = 1
  }
  if (n < 1) {
    slideIndex = slides.length
  }
  for (i = 0; i < slides.length; i++) {
    slides[i].style.display = "none";
  }
  for (i = 0; i < dots.length; i++) {
    dots[i].className = dots[i].className.replace(" active", "");
  }
  slides[slideIndex - 1].style.display = "block";
  dots[slideIndex - 1].className += " active";
}

//automatic

var slideIndexAuto = 0;
showSlidesAuto();

function showSlidesAuto() {
  var i;
  var slides = document.getElementsByClassName("item");
  var dots = document.getElementsByClassName("dot");
  for (i = 0; i < slides.length; i++) {
    slides[i].style.display = "none";
    dots[i].className = dots[i].className.replace(" active", "");
  }
  slideIndexAuto++;
  if (slideIndexAuto > slides.length) {
    slideIndexAuto = 1
  }
  slides[slideIndexAuto - 1].style.display = "block";
  dots[slideIndexAuto - 1].className += " active";
  setTimeout(showSlidesAuto, 5000);
}
.slider {
  width: 65%;
  max-width: 940px;
  height: 500px;
  border-radius: 0.25rem;
  position: relative;
  overflow: hidden;
}

.slider .left-slide,
.slider .right-slide {
  position: absolute;
  height: 40px;
  width: 40px;
  background-color: #444444;
  border-radius: 50%;
  color: #ffffff;
  font-size: 20px;
  top: 50%;
  cursor: pointer;
  margin-top: -20px;
  text-align: center;
  line-height: 40px;
}

.slider .left-slide:hover,
.slider .right-slide:hover {
  box-shadow: 0px 0px 10px black;
  background-color: #29a8e2;
}

.slider .left-slide {
  left: 30px;
}

.slider .right-slide {
  right: 30px;
}

.slider .slider-items .item img {
  width: 100%;
  height: 500px;
  display: block;
}

.slider .slider-items .item {
  position: relative;
  transition: 4s;
}

.slider .slider-items .item .caption {
  position: absolute;
  width: 100%;
  height: 100%;
  bottom: 0px;
  left: 0px;
  background-color: rgba(0, 0, 0, .5);
}
<div class="slider">
  <div class="slider-items">
    <div class="item fade">
      <img src="/images/cs-slider-high.jpg" />
      <div class="caption">
        <p class="caption-text">COMING</p>
        <p class="caption-text">OKTOBER 10th</p>
      </div>
    </div>

    <div class="item fade">
      <img src="/images/building-slider.jpg" />
      <div class="caption">
        <p class="caption-text-2">Blackstoneroad 109</br>
        </p>
      </div>
    </div>
    <div class="item fade">
      <img src="/images/kontact-slider.jpg" />
      <div class="caption">
        <p class="caption-text-3">Coffee<br>Drinks<br>Food<br>& More</p>
      </div>
    </div>
    <div class="item fade">
      <img src="/images/seminar-slider.jpg" />
      <div class="caption">
        <p class="caption-text-3">Seminar Rooms<br>Inspiration<br>Shopping<br>& More</p>
      </div>
    </div>

  </div>

  <!-- Next and previous buttons -->
  <a class="prev" onclick="plusSlides(-1)">&#10094;</a>
  <a class="next" onclick="plusSlides(1)">&#10095;</a>

</div>

<!-- The dots/circles -->
<div class="align-text-center">
  <span class="dot" onclick="currentSlide(1)"></span>
  <span class="dot" onclick="currentSlide(2)"></span>
  <span class="dot" onclick="currentSlide(3)"></span>
  <span class="dot" onclick="currentSlide(3)"></span>
</div>
Max Herrmann
  • 83
  • 1
  • 5
  • My advice would be to only toggle/change class names. Put all of your style parameters inside a class, this should include display block/none aswell, also any transitions. Don't use js to change the property of an element, just pass everything via a class name. I will see if I can add an example later, but I am sure lots of other people will help you out. – lharby Sep 28 '20 at 17:39
  • 1
    To trigger a transition on a css class, you have to change the existing class on an object to that class. Usually, this is done by doing `elementobject.classList.remove("other_class");` followed by `elementobject.classList.add("class_with_transition");` (where elementobject is the variable pointing to the element). So, you need to switch between two classes. – ATD Sep 28 '20 at 17:56
  • Any chance you could give me an example with a working transition, triggered by javascript class add? It just won't work for me. Just for clarification: Getting the Image to change is not the problem, neither giving the div an animation effect, its getting the smooth "slide effect" using the transition element. – Max Herrmann Sep 28 '20 at 19:44
  • @MaxHerrmann see my answer, hopefully this helps you! – lharby Sep 30 '20 at 08:43

2 Answers2

1

How is this: http://jsfiddle.net/lharby/qox05y96/

For simplification I have stripped out the dot animation (although that code is closer to the effect you want).

Here is the simplified JS:

function showSlides(n) {
  var i;
  var slides = document.getElementsByClassName("item");
  var dots = document.getElementsByClassName("dot");
  if (n > slides.length) {
    slideIndex = 1
  }
  if (n < 1) {
    slideIndex = slides.length
  }
  for (i = 0; i < slides.length; i++) {
    slides[i].classList.remove('active'); // this is updated
  }
  slides[slideIndex - 1].className += " active";
}

//automatic
var slideIndexAuto = 0;
showSlidesAuto();

function showSlidesAuto() {
  var i;
  var slides = document.getElementsByClassName("item");
  var dots = document.getElementsByClassName("dot");
  for (i = 0; i < slides.length; i++) {
    slides[i].classList.remove('active'); // this is updated
    
  }
  slideIndexAuto++;
  if (slideIndexAuto > slides.length) {
    slideIndexAuto = 1
  }
  slides[slideIndexAuto - 1].classList.add('active'); // this is updated
  setTimeout(showSlidesAuto, 4000);
}

This means we also have to change the css. display none/block is harder to animate with css transitions. So I have used opacity: 0/1 and visibility: hidden/visible. However one other trade off is that that the item elements cannot be positioned relatively this would stack them on top of one another (or side by side) usually for an animated slideshow you would use position absolute for each slide, but I realise that causes you another issue.

CSS:

.slider .slider-items .item {
    visibility: hidden;
    opacity: 0;
    transition: 4s;
}

.slider .slider-items .item.active {
    visibility: visible;
    opacity: 1;
    transition: 4s;
}

At least now all of the css is handled within the css and the js purely adds or removes a class name which I feel makes it a bit easier to update.

lharby
  • 3,057
  • 5
  • 24
  • 56
  • Hey, thanks for your reply! I tried switching around the js syntax as well but It never resulted in the wanted effect. Your solution at least made the transition effect possible on the first image (item) slide but unfortunately, It won't display any Images after that first slide. Tried playing around with the Syntax and the CSS classes but just made it worse :( Thanks again for your reply though! If you find the time to try out your code with images and experience similar problems and maybe even have a solution for it, please let me know! – Max Herrmann Sep 30 '20 at 18:23
  • //Edit As you have stated above, It probably has something to do with the 'position: relative' class. My head is smoking getting that slider to work properly, the best thing to do here would probably be getting a fresh start. – Max Herrmann Sep 30 '20 at 18:44
  • A couple of things, in order to test images on SO and jsfiddle we need the absolute url, so http://yoursite.com/img/image1.jpg etc. The other option might be to wrap the image inside a span which can be positioned relatively and then the image inside can be positioned absolutely, but it would require markup changes. – lharby Oct 01 '20 at 07:57
0

There are priorities as far as what CSS deems should happen. Take a look at this and let me know if it changes anything for you. If not I'll try and run the code and fix your errors. I want to let you know in advance, I am a pure JS developer. When I need CSS or HTML I create it in JS. I want you to try first, thus it will make you a better developer.

https://www.thebookdesigner.com/2017/02/styling-priorities-css-for-ebooks-3/

Boheyga
  • 52
  • 5