0

I have a slider in the snippet below. If you run it, you'll notice when you navigate the slider, the content comes in underneath the slider, and then up into the slider container.

How can I fix that so it just slides left and right without breaking content?

class Slider {
  constructor(sliderElem) {
    this.slider = sliderElem;
    this.sliderItems = sliderElem.getElementsByClassName("testimonial__item");
    this.nextBtn = sliderElem.querySelector(
      ".testimonial__slider-control-next"
    );
    this.prevBtn = sliderElem.querySelector(
      ".testimonial__slider-control-prev"
    );
    this.currentIndex = 0;
    this.prevItemIndex = this.sliderItems.length - 1;
    this.nextItemIndex = 1;
    this.isSliding = false;

    // Set Item Indexs if active class is specified on an element other than the first.
    for (let i = 0; i < this.sliderItems.length; i++) {
      if (this.sliderItems[i].classList.contains("active")) {
        this.currentIndex = i;
        if (i + 1 === this.sliderItems.length) {
          this.nextItemIndex = 0;
        }
        this.nextItemIndex = i + 1;
        if (i !== 0) {
          this.prevItemIndex = i - 1;
        }
        break;
      }
    }
    this.setEventListeners();
  }
  setEventListeners() {
    this.prevBtn.addEventListener("click", () => {
      this.prev();
    });
    this.nextBtn.addEventListener("click", () => {
      this.next();
    });
  }
  setIndices(direction) {
    let index;
    if (direction === "NEXT") {
      index =
        this.currentIndex === this.sliderItems.length - 1 ?
        0 :
        this.currentIndex + 1;
    }
    if (direction === "PREV") {
      index =
        this.currentIndex === 0 ?
        this.sliderItems.length - 1 :
        this.currentIndex - 1;
    }
    if (index === 0) {
      this.currentIndex = index;
      this.nextItemIndex = index + 1;
      this.prevItemIndex = this.sliderItems.length - 1;
    } else if (index === this.sliderItems.length - 1) {
      this.currentIndex = this.sliderItems.length - 1;
      this.nextItemIndex = 0;
      this.prevItemIndex = this.currentIndex - 1;
    } else {
      this.currentIndex = index;
      this.nextItemIndex = index + 1;
      this.prevItemIndex = index - 1;
    }
  }
  next() {
    if (this.isSliding) return;
    this.isSliding = !this.isSliding;
    this.sliderItems[this.nextItemIndex].classList.add("next-item");
    setTimeout(() => {
      this.sliderItems[this.currentIndex].classList.add("slide-next");
      this.sliderItems[this.nextItemIndex].classList.add("slide-end");
      this.sliderItems[this.nextItemIndex].classList.add("active");
    }, 20);
    setTimeout(() => {
      this.sliderItems[this.nextItemIndex].classList.remove(
        "next-item",
        "slide-end"
      );
      this.sliderItems[this.currentIndex].classList.remove(
        "slide-next",
        "active"
      );
      this.setIndices("NEXT");
      this.isSliding = false;
    }, 400);
  }
  prev() {
    if (this.isSliding) return;
    this.isSliding = !this.isSliding;
    this.sliderItems[this.prevItemIndex].classList.add("prev-item");
    setTimeout(() => {
      this.sliderItems[this.currentIndex].classList.add("slide-prev");
      this.sliderItems[this.prevItemIndex].classList.add("slide-end");
      this.sliderItems[this.prevItemIndex].classList.add("active");
    }, 20);
    setTimeout(() => {
      this.sliderItems[this.prevItemIndex].classList.remove(
        "prev-item",
        "slide-end"
      );
      this.sliderItems[this.currentIndex].classList.remove(
        "slide-prev",
        "active"
      );
      this.setIndices("PREV");
      this.isSliding = false;
    }, 400);
  }
}

const slider = new Slider(document.querySelector(".testimonial__slider"));
.container {
  padding: 2em;
}

.testimonial {
  display: flex;
  flex-direction: column;
  /* slide animation */
}
.testimonial__slider {
  margin-top: 2rem;
  height: auto;
  overflow: hidden;
  position: relative;
  display: flex;
  flex-direction: column;
}
.testimonial .arrows {
  display: flex;
  margin-right: auto;
  margin-top: 2rem;
}
@media (min-width: 768px) {
  .testimonial .arrows {
    margin-right: unset;
    margin-left: auto;
    margin-top: unset;
  }
}
.testimonial__controls {
  display: flex;
  flex-direction: column;
  margin-bottom: 2rem;
}
@media (min-width: 768px) {
  .testimonial__controls {
    display: flex;
    flex-direction: row;
    align-items: center;
  }
}
.testimonial__slider .testimonial__item.active, .testimonial__slider .testimonial__item.prev-item, .testimonial__slider .testimonial__item.next-item {
  display: flex;
}
.testimonial__img {
  min-width: 40%;
}
.testimonial__img img {
  height: 100%;
}
.testimonial__slider .testimonial__item {
  height: 100%;
  width: 100%;
  display: none;
  transition: transform 0.2s ease;
}
.testimonial__item {
  background: #F2F5F9;
  display: flex;
  flex-direction: column;
  transition: all 0.2s ease;
}
@media (min-width: 576px) {
  .testimonial__item {
    display: flex;
    flex-direction: row;
  }
}
.testimonial__content {
  display: flex;
  flex-direction: column;
  padding: 2.75rem 2.5rem 2.5rem;
  justify-content: space-between;
}
.testimonial__credits {
  display: flex;
  flex-direction: column;
  margin-top: 2rem;
  border-left: 4px solid #005fec;
  padding-left: 0.75rem;
}
.testimonial__name {
  margin-bottom: 0.5rem;
}
.testimonial__item.prev-item, .testimonial__item.active.slide-next {
  transform: translateX(-100%);
}
.testimonial__item.active.slide-prev, .testimonial__item.next-item {
  transform: translateX(100%);
}
.testimonial__item.prev-item.slide-end, .testimonial__item.next-item.slide-end {
  transform: translateX(0);
}
.testimonial__slider-control-prev, .testimonial__slider-control-next {
  cursor: pointer;
  display: flex;
}
.testimonial__slider-control-prev {
  left: 20px;
  margin-right: 1.25rem;
}
.testimonial__slider-control-prev:hover {
  opacity: 1;
}
.testimonial__slider-control-next {
  right: 20px;
}
.testimonial__slider-control-next:hover {
  opacity: 1;
}
<div class="container">
  <div class="testimonial">
    <div class="testimonial__slider">
      <div class="testimonial__controls">
        <h3>Lorem ipsum dolor sit amet.</h3>
        <div class="arrows">
          <span class="testimonial__slider-control-prev" role="button">
            <img aria-hidden="true" src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Feather-arrows-arrow-left.svg/768px-Feather-arrows-arrow-left.svg.png" height="25" width="25" alt="Previous Slide Button">
          </span>
          <span class="testimonial__slider-control-next" role="button">
            <img aria-hidden="true" src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Feather-arrows-arrow-right.svg/1200px-Feather-arrows-arrow-right.svg.png" height="25" width="25" alt="Next Slide Button">
          </span>
        </div>
      </div>
      <div class="testimonial__item active">
        <div class="testimonial__img">
          <img class="img-fluid" src="https://nextivaweb.imgix.net/heroes/case-study/Case-Study-Conan-hero.jpg?w=336&h=412&auto=format&crop=focalpoint&fit=crop&fp-x=.75&fp-z=1.3&fp-y=.39" alt="">
        </div>
        <div class="testimonial__content">
          <div class="testimonial__text">
            <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Deleniti laboriosam fugiat perferendis blanditiis, dignissimos temporibus sunt aliquam sequi quia! Deleniti earum quibusdam dolorem accusantium ipsum?</p>
          </div>
          <div class="testimonial__credits">
            <span class="testimonial__name kicker kicker--bold">Lorem, ipsum.</span>
            <span class="testimonial__position kicker kicker--light">Lorem ipsum dolor sit amet,
              Burbank,
              CA</span>
          </div>
        </div>
      </div>
      <div class="testimonial__item">
        <div class="testimonial__img">
          <img class="img-fluid" src="https://sandbox-uploads.imgix.net/u/1630477471-dd0cd5b16967417586c822d6dabcb995?w=336&h=412&auto=format" alt="">
        </div>
        <div class="testimonial__content">
          <div class="testimonial__text">
            <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Architecto veniam eos, omnis commodi doloribus dignissimos at ad quia asperiores nulla.</p>
          </div>
          <div class="testimonial__credits">
            <span class="testimonial__name kicker kicker--bold">Lorem, ipsum.</span>
            <span class="testimonial__position kicker kicker--light">Lorem ipsum dolor sit amet.</span>
          </div>
        </div>
      </div>
      <div class="testimonial__item">
        <div class="testimonial__img">
          <img class="img-fluid" src="https://sandbox-uploads.imgix.net/u/1630477587-e54d61f4eef5e36c72dccd1fc0463514?w=336&h=412&auto=format" alt="">
        </div>
        <div class="testimonial__content">
          <div class="testimonial__text">
            <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Impedit nesciunt aliquam cum commodi perferendis, iusto numquam eum neque nulla natus adipisci facere officiis.</p>
          </div>
          <div class="testimonial__credits">
            <span class="testimonial__name kicker kicker--bold">Lorem, ipsum.</span>
            <span class="testimonial__position kicker kicker--light">Lorem ipsum dolor sit amet,
              Burbank,
              CA</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
Millhorn
  • 2,953
  • 7
  • 39
  • 77

1 Answers1

0

display: flex uses some properties of display: block unless otherwise specified. One of those is that it takes up the entire horizontal space and pushes other items in the same space down to their own row.

Your .active class is not removing the display until after the __item is off screen. Because they are relatively positioned, they must respect all other __items' relative location.

An easier approach to this, which requires a lot of extra definitions, is to use position: absolute; top: 0;, and then fiddle with the other stuff accordingly. You might also try inline-flex. I'm less versed in that, however, so I'd start here, where they do a great job of explaining the difference between a container and an item:

https://stackoverflow.com/a/27459133/6775641

Clayton Engle
  • 582
  • 3
  • 17
  • I should clarify; what you're really asking is about the difference of block level and inline level element displays. You are using a flex container (the one with __item) that is at the block level. The post I added goes into more detail. To get an even better understanding, check here to see how floats break this model, and how clear fix changes their formatting context. It may help it all make sense (even though we aren't dealing with floats in your case): https://stackoverflow.com/a/38873243/6775641 – Clayton Engle Sep 02 '21 at 17:57