1

I have a simple CSS transform/transition for a toggle switch. It toggles a .slider-click class when I click on it. I want to perform a second transition that "reverses" the effect when I click on it again. But, obviously it just removes the class. Please run my code snippet to see what I mean. How do I achieve this? Thanks.

      const slider = document.querySelector('.slider')
      const circle = document.querySelector('.slider-circle')
      
      slider.addEventListener('click', (e)=>{
        circle.classList.toggle('slider-click');
      })
.slider {
    background-color: hsl(237, 63%, 64%);
    border-radius: 75px;
    width: 34vw;
    height: 21vw;
    display: flex;
    justify-content: flex-start;
    align-content: flex-start;
}
.slider:hover {
    opacity: 50%;
    cursor: pointer;
}
.slider-circle {
    height: 17.36vw;
    width: 17.36vw;
    border-radius: 50%;
    background-color: #ffffff;
    margin: 5%
}

.slider-click {
    transform: translateX(13vw);
    transition: .2s;
}

/* Something like this when clicked again */
.slider-return {
    transform: translateX(-13vw);
    transition: .2s;
}
          <div class="slider-content">
            <div class="slider">
                <div class="slider-circle"></div>
            </div>
          </div>
njboot
  • 147
  • 1
  • 10

4 Answers4

1

Set the transition: .2s; inside the default element, not once it receives the active class.

// slider? It's more kindof a checkbox
const checkbox = document.querySelectorAll('.checkbox'); // use all! It's a class after all
const checboxToggle = (ev) => ev.currentTarget.classList.toggle('is-active');
checkbox.forEach(el => el.addEventListener('click', checboxToggle));
.checkbox {
  background-color: hsl(237, 63%, 64%);
  border-radius: 21vw;
  width: 34vw;
  height: 21vw;
  display: flex;
  justify-content: flex-start;
  align-content: flex-start;
  cursor: pointer;
}

.checkbox:before {
  content: "";
  height: 17.36vw;
  width: 17.36vw;
  border-radius: 50%;
  background-color: #ffffff;
  margin: 5%;
  transition: .2s; /* USE IT HERE! */
}

.checkbox.is-active:before {
  transform: translateX(13vw);
}
<div class="checkbox"></div>

Additionally:

  • Use the right wording. There's nothing to slide. It's more like a checkbox.
  • Use querySelectorAll since you use classes! And .forEach() allthe retrieved elements.
  • You don't need any inner elements. Use the :before or :after pseudos
  • Add the desired class directly to the main .checkbox element.
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
-1

I guess this is what you want, you just add a class clicked to the circle, which will set css translateX(13vw) and reset it to zero when clicked again.

const slider = document.querySelector('.slider')
const circle = document.querySelector('.slider-circle')

slider.addEventListener('click', (e)=>{
  circle.classList.toggle('clicked');
})
.slider {
    background-color: hsl(237, 63%, 64%);
    border-radius: 75px;
    width: 34vw;
    height: 21vw;
    display: flex;
    justify-content: flex-start;
    align-content: flex-start;
}
.slider:hover {
    opacity: 50%;
    cursor: pointer;
}
.slider-circle {
    height: 17.36vw;
    width: 17.36vw;
    border-radius: 50%;
    background-color: #ffffff;
    margin: 5%;
    transition: all .2s ease-out;
    transform: translateX(0);
}

.clicked {
    transform: translateX(13vw);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="slider-content">
  <div class="slider">
      <div class="slider-circle"></div>
  </div>
</div>
dutchsociety
  • 575
  • 4
  • 22
-1

      const slider = document.querySelector('.slider')
      const circle = document.querySelector('.slider-circle')
      let toggled = false
      slider.addEventListener('click', (e)=>{
        if(toggled) {
          circle.classList.remove('slider-click');
          circle.classList.add('slider-return');
          toggled = false;
        } else {
          circle.classList.remove('slider-return');
          circle.classList.add('slider-click');
          toggled = true;
        }
      })
.slider {
    background-color: hsl(237, 63%, 64%);
    border-radius: 75px;
    width: 34vw;
    height: 21vw;
    display: flex;
    justify-content: flex-start;
    align-content: flex-start;
}
.slider:hover {
    opacity: 50%;
    cursor: pointer;
}
.slider-circle {
    height: 17.36vw;
    width: 17.36vw;
    border-radius: 50%;
    background-color: #ffffff;
    margin: 5%
}

.slider-click {
    transform: translateX(13vw);
    transition: .2s;
}

/* Something like this when clicked again */
.slider-return {
    transform: initial;
    transition: .2s;
}
          <div class="slider-content">
            <div class="slider">
                <div class="slider-circle"></div>
            </div>
          </div>
yen
  • 1,769
  • 2
  • 15
  • 43
  • Such a bad solution to use needlessly two classes. – Roko C. Buljan May 25 '20 at 16:27
  • 1
    @RokoC.Buljan - I answered the poster's question directly: they had "needlessly used two classes", so I gave the solution which makes the "two needlessly used classes" work. I was rather excited about being able to find the solution to a CSS question! That brief joy is gone, but I guess I have in its place the knowledge you just dropped. So ... thanks? – yen May 25 '20 at 16:34
-1

Start by using a checkbox and use :before and :after pseudo classes.

Use of Javascript will not be necessary.

See w3schools for more information on how to do this.

J Vines
  • 182
  • 1
  • 16
  • w3schools is still at this day the worst learning resource out there. Also, link-only answers are not in the expected format for this site. – Roko C. Buljan May 25 '20 at 16:29