0
votes

I have a problem with a slider: slide content should stay fixed to the right bottom corner and preform animation there, but instead it first moves along the slider and then animates back to the position. I would like to make it that when the slide comes in it slides from right to left, and when slides goes away it slides back to position where it is not visible.

Here is my code:

var theSlider = {
  track: document.querySelector('.m-tract-slider-wrapp'),
  // has to match `transition-duration` in CSS:
  duration: 450,
  reset: function() {
    var slides = document.querySelectorAll('.m-tract-slider-wrapp > div');
    for (var i = 0; i < slides.length; i++) {
      slides[i].className = '';
      slides[i].classList.add(i > 1 ? 'after' : (i ? 'current' : 'before'))
    }
  },

  init: function() {
    theSlider.reset();
    theSlider.track.classList.remove('not-loaded')
  },

  next: function() {
    theSlider.track.classList.add('go-right');
    setTimeout(function() {
      var firstSlide = document.querySelector('.m-tract-slider-wrapp > div:first-child');
      theSlider.track.appendChild(firstSlide);
      theSlider.reset();
      theSlider.track.classList.remove('go-right')
    }, theSlider.duration)
  },

  prev: function() {
    theSlider.track.classList.add('go-left');
    setTimeout(function() {
      var lastSlide = document.querySelector('.m-tract-slider-wrapp > div:last-child');
      theSlider.track.insertBefore(lastSlide, theSlider.track.firstChild);
      theSlider.reset();
      theSlider.track.classList.remove('go-left')
    }, theSlider.duration)
  },

  prevButton: document.querySelector('.slide-left'),
  nextButton: document.querySelector('.slide-right')
};

window.addEventListener("load", theSlider.init);
theSlider.prevButton.addEventListener('click', theSlider.prev);
theSlider.nextButton.addEventListener('click', theSlider.next);
.m-tract-slider {
  width: 100%;
  height: 75vh;
  margin: 5em auto;
  position: relative;
  overflow: hidden;
  background-color: #f5f5f5
}

.m-tract-slider-wrapp {
  height: 100%;
  -webkit-transition: all 350ms cubic-bezier(.08, .13, 0, .81);
  -moz-transition: all 350ms cubic-bezier(.08, .13, 0, .81);
  -o-transition: all 350ms cubic-bezier(.08, .13, 0, .81);
  transition: all 350ms cubic-bezier(.08, .13, 0, .81);
  opacity: 1
}

.m-tract-slider-wrapp.not-loaded {
  opacity: 0
}

.m-tract-slider-wrapp>div {
  height: 100%;
  position: absolute;
  background: transparent no-repeat 50% 50%/cover;
  width: 100%
}

.m-tract-slider-wrapp>div.before {
  margin-left: -100%
}

.m-tract-slider-wrapp>div.current+div {
  margin-left: 100%
}

.m-tract-slider-wrapp>div.current .m-tract-slide-content {
  transform: translateX(0);
  -ms-transform: translateX(0);
  -webkit-transform: translateX(0);
  -webkit-transition: transform 350ms ease-in;
  -moz-transition: transform 350ms ease-in;
  -o-transition: transform 350ms ease-in;
  transition: transform 350ms ease-in;
  transition-delay: .6s;
  margin-left: 0
}

.m-tract-slider-wrapp>div.after~div {
  opacity: 0
}

.m-tract-slide-content {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 40%;
  background: #fff;
  padding: 3em;
  margin: 0;
  height: 50vh;
  transform: translateX(100%);
  -ms-transform: translateX(100%);
  -webkit-transform: translateX(100%);
  -webkit-transition: transform 350ms ease-in;
  -moz-transition: transform 350ms ease-in;
  -o-transition: transform 350ms ease-in;
  transition: transform 350ms ease-in;
  transition-delay: .6s
}

.m-tract-slide_title {
  font-size: 32px;
  font-weight: 700;
  color: #212121
}

.m-tract-slide_text {
  font-size: 18px;
  display: block;
  margin-top: 2em;
  color: #ccc;
  font-weight: 300
}

.m-tract-slider-control {
  position: absolute;
  bottom: 0;
  left: 0;
  background: #fff;
  padding: 1em
}

.m-tract-slider-btn {
  display: inline-block;
  cursor: pointer;
  margin-left: 1em
}

.m-tract-slider-btn:first-child {
  margin-left: 0
}

.go-right div {
  transform: translateX(-100%);
  -ms-transform: translateX(-100%);
  -webkit-transform: translateX(-100%)
}

.go-left div {
  transform: translateX(100%);
  -ms-transform: translateX(100%);
  -webkit-transform: translateX(100%)
}

.go-left div,
.go-right div {
  -webkit-transition: transform 450ms cubic-bezier(.4, 0, .2, 1);
  -moz-transition: transform 450ms cubic-bezier(.4, 0, .2, 1);
  -o-transition: transform 450ms cubic-bezier(.4, 0, .2, 1);
  transition: transform 450ms cubic-bezier(.4, 0, .2, 1)
}
<div class="m-tract-slider">
  <div class="m-tract-slider-wrapp">

    <div style="background-image:url('https://static.pexels.com/photos/126282/pexels-photo-126282.jpeg')" class="before">
      <div class="m-tract-slide-content first-slide">
        <span class="m-tract-slide_title">Gde ćeš provesti večnost?</span>
        <span class="m-tract-slide_text">
          Lorem ipsum dolor sit amet, consectetur adipisicing elit.
          Voluptatum ea assumenda, nam quia, distinctio omnis. Aspernatur,
          molestias nostrum dolores? Voluptas sequi labore cum ipsum
          necessitatibus possimus, soluta veritatis aut dicta.
        </span>
      </div>
    </div>

    <div style="background-image:url('https://static.pexels.com/photos/29017/pexels-photo-29017.jpg')" class="current">
      <div class="m-tract-slide-content first-slide">
        <span class="m-tract-slide_title">Title 2</span>
        <span class="m-tract-slide_text">
          Lorem ipsum dolor sit amet, consectetur adipisicing elit.
          Voluptatum ea assumenda, nam quia, distinctio omnis. Aspernatur,
          molestias nostrum dolores? Voluptas sequi labore cum ipsum
          necessitatibus possimus, soluta veritatis aut dicta.
         </span>
      </div>
    </div>

    <div style="background-image:url('https://static.pexels.com/photos/70760/dandelion-dandelion-seeds-taraxacum-fluffy-70760.jpeg')" class="after">
      <div class="m-tract-slide-content first-slide">
        <span class="m-tract-slide_title">Title 3</span>
        <span class="m-tract-slide_text">
          Lorem ipsum dolor sit amet, consectetur adipisicing elit.
          Voluptatum ea assumenda, nam quia, distinctio omnis. Aspernatur,
          molestias nostrum dolores? Voluptas sequi labore cum ipsum
          necessitatibus possimus, soluta veritatis aut dicta.
        </span>
      </div>
    </div>

  </div>

  <div class="m-tract-slider-control">
    <div class="m-tract-slider-btn slide-left">Prev</div>
    <div class="m-tract-slider-btn slide-right">Next</div>
  </div>
</div>
1

1 Answers

1
votes

When you deal with properties that affect animations you need to be very careful about your selectors.

The .go-right div and .go-left div selectors are affecting each sibling of .go-right and .go-left, while you probably only want the immediate siblings (the slides) to be affected, so I replaced them with .go-right>div and .go-left>div :

var theSlider = {
  track: document.querySelector('.m-tract-slider-wrapp'),
  // has to match `transition-duration` in CSS:
  duration: 450,
  reset: function() {
    var slides = document.querySelectorAll('.m-tract-slider-wrapp > div');
    for (var i = 0; i < slides.length; i++) {
      slides[i].className = '';
      slides[i].classList.add(i > 1 ? 'after' : (i ? 'current' : 'before'))
    }
  },

  init: function() {
    theSlider.reset();
    theSlider.track.classList.remove('not-loaded')
  },

  next: function() {
    theSlider.track.classList.add('go-right');
    setTimeout(function() {
      var firstSlide = document.querySelector('.m-tract-slider-wrapp > div:first-child');
      theSlider.track.appendChild(firstSlide);
      theSlider.reset();
      theSlider.track.classList.remove('go-right')
    }, theSlider.duration)
  },

  prev: function() {
    theSlider.track.classList.add('go-left');
    setTimeout(function() {
      var lastSlide = document.querySelector('.m-tract-slider-wrapp > div:last-child');
      theSlider.track.insertBefore(lastSlide, theSlider.track.firstChild);
      theSlider.reset();
      theSlider.track.classList.remove('go-left')
    }, theSlider.duration)
  },

  prevButton: document.querySelector('.slide-left'),
  nextButton: document.querySelector('.slide-right')
};

window.addEventListener("load", theSlider.init);
theSlider.prevButton.addEventListener('click', theSlider.prev);
theSlider.nextButton.addEventListener('click', theSlider.next);
.m-tract-slider {
  width: 100%;
  height: 75vh;
  margin: 5em auto;
  position: relative;
  overflow: hidden;
  background-color: #f5f5f5
}

.m-tract-slider-wrapp {
  height: 100%;
  transition: all 350ms cubic-bezier(.08, .13, 0, .81);
  opacity: 1
}

.m-tract-slider-wrapp.not-loaded {
  opacity: 0
}

.m-tract-slider-wrapp>div {
  height: 100%;
  position: absolute;
  background: transparent no-repeat 50% 50%/cover;
  width: 100%
}

.m-tract-slider-wrapp>div.before {
  margin-left: -100%
}

.m-tract-slider-wrapp>div.current+div {
  margin-left: 100%
}

.m-tract-slider-wrapp>div.current .m-tract-slide-content {
  transform: translateX(0);
  margin-left: 0
}

.m-tract-slider-wrapp>div.after~div {
  opacity: 0
}

.m-tract-slide-content {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 40%;
  background: #fff;
  padding: 3em;
  margin: 0;
  height: 50vh;
  transform: translateX(100%);
  transition: transform 350ms ease-in;
  transition-delay: 0s; /* was .6s */
}

.m-tract-slide_title {
  font-size: 32px;
  font-weight: 700;
  color: #212121
}

.m-tract-slide_text {
  font-size: 18px;
  display: block;
  margin-top: 2em;
  color: #999;
  font-weight: 300
}

.m-tract-slider-control {
  position: absolute;
  bottom: 0;
  left: 0;
  background: #fff;
  padding: 1em
}

.m-tract-slider-btn {
  display: inline-block;
  cursor: pointer;
  margin-left: 1em
}

.m-tract-slider-btn:first-child {
  margin-left: 0
}

.go-right > div {
  transform: translateX(-100%);
}

.go-left > div {
  transform: translateX(100%);
}

.go-left > div,
.go-right > div {
  transition: transform 450ms cubic-bezier(.4, 0, .2, 1)
}
<div class="m-tract-slider">
  <div class="m-tract-slider-wrapp">

    <div style="background-image:url('https://static.pexels.com/photos/126282/pexels-photo-126282.jpeg')" class="before">
      <div class="m-tract-slide-content first-slide">
        <span class="m-tract-slide_title">Gde ćeš provesti večnost?</span>
        <span class="m-tract-slide_text">
          Lorem ipsum dolor sit amet, consectetur adipisicing elit.
          Voluptatum ea assumenda, nam quia, distinctio omnis. Aspernatur,
          molestias nostrum dolores? Voluptas sequi labore cum ipsum
          necessitatibus possimus, soluta veritatis aut dicta.
        </span>
      </div>
    </div>

    <div style="background-image:url('https://static.pexels.com/photos/29017/pexels-photo-29017.jpg')" class="current">
      <div class="m-tract-slide-content first-slide">
        <span class="m-tract-slide_title">Title 2</span>
        <span class="m-tract-slide_text">
          Lorem ipsum dolor sit amet, consectetur adipisicing elit.
          Voluptatum ea assumenda, nam quia, distinctio omnis. Aspernatur,
          molestias nostrum dolores? Voluptas sequi labore cum ipsum
          necessitatibus possimus, soluta veritatis aut dicta.
         </span>
      </div>
    </div>

    <div style="background-image:url('https://static.pexels.com/photos/70760/dandelion-dandelion-seeds-taraxacum-fluffy-70760.jpeg')" class="after">
      <div class="m-tract-slide-content first-slide">
        <span class="m-tract-slide_title">Title 3</span>
        <span class="m-tract-slide_text">
          Lorem ipsum dolor sit amet, consectetur adipisicing elit.
          Voluptatum ea assumenda, nam quia, distinctio omnis. Aspernatur,
          molestias nostrum dolores? Voluptas sequi labore cum ipsum
          necessitatibus possimus, soluta veritatis aut dicta.
        </span>
      </div>
    </div>

  </div>

  <div class="m-tract-slider-control">
    <div class="m-tract-slider-btn slide-left">Prev</div>
    <div class="m-tract-slider-btn slide-right">Next</div>
  </div>
</div>

A few more tips on how to keep developing manageable:

  • use shorter classnames (you only need one specific longer class or id to apply your CSS to specific elements. So use shorter classnames for its children.
  • do not copy/paste transition or transforms over different states of the same element. Just place them on the state that's always active and only override the property that changes. It really improves animation performance and also increases your ability to understand and control it.
  • only prefix your properties after you're done developing, as a last step; otherwise, they'll clutter up your "workspace" without adding anything, really;
  • when you don't have a reason to use em, use rem. If you want your slider's paddings and margins to be affected by <body>'s font-size use rem. If you want it fixed to whatever you set on slider, use em (and set font-size on your slider).

A quick ran-down of those principles applied to what you have (it's not perfect and can be further streamlined, but I think you'll find it easier to workwith). I also transformed your CSS into SCSS as, again, it's easier to control.

Don't be intimidated by SCSS. You don't have to use variables and mixins (although they are pretty powerful and handy once you learn them). But I'm sure you'll find the simple class nesting handy for starters.
To get the result from the snippet, inspect source and you'll find it transformed into CSS.