Pure Javascript alternatives to toggling a CSS class?

Viewed 368

My goal is to rotate a div 180deg on each click, without toggling CSS classes.

I can achieve one rotation with the first click (.style.transform = "rotate(180deg)";), but any subsequent click has no effect.

BTW, why exactly is that? The div's Id hasn't changed, so, in theory, the same trigger (a click, in this case) should call the same function, right? But it doesn't. I wonder what's the logic here, what's the technical explanation, and, moving to practice, how can I further manipulate this post-div (that is, the original div after its JavaScript manipulation) -- again, without toggling CSS classes.

function rotate() {
    document.getElementById("container").style.transform = 
    "rotate(180deg)";
}
.container {
    width: 200px;
    height: 400px;
    border: 5px solid;
    border-bottom-color: blue;
    border-top-color: red;
}
<div class="container" id="container" onclick="rotate()"></div>

    

6 Answers

The first time you change the transformation from "" to "rotate(180deg)", so it rotates.

Subsequent times you change it from "rotate(180deg)" to "rotate(180deg)" … which isn't a change at all, so nothing happens.

If you want to change it, then you need to actually assign a different value to it.

e.g.

const style = document.getElementById("container").style;
if (style.transform) {
    style.transform = "";
} else {
    style.transform = "rotate(180deg)";
}

Toggling a class is simpler, and clearer.

document.querySelector("#container").addEventListener("click", e => e.currentTarget.classList.toggle("rotated"));
.container {
  width: 200px;
  height: 400px;
  border: 5px solid;
  border-bottom-color: blue;
  border-top-color: red;
  transition: transform 0.25s;
}

.rotated {
  transform: rotate(180deg);
}
<div class="container" id="container"></div>

The reason why the div is not rotating after first function call is that you are setting the transform style property to constant value (180deg). After first call the transform is performed and all following calls set transform to exactly the same value. In order to make it work, you have to increment rotate property each time you call the function.

In example:

let rotation = 0;

function rotate() {
    document.getElementById("container").style.transform =  `rotate(${rotation}deg)`;
    rotation = (rotation + 180) % 360;
}

I made a fiddle , but basically, you can't rotate for the same value. Of course this is very raw, but prove the concept for you to understand. You can do it more programatically of course.

document.getElementById('container').addEventListener('click', function () {
  this.style.transform = this.style.transform == "rotate(180deg)" ? "rotate(-90deg)" : "rotate(180deg)";
  }
);

You can check this out: tutorial

You need to check the transform value and then rotate it anti-clockwise.

Here is the code:

HTML

<div class="container" id="container" onclick="rotate()"></div>

CSS

.container {
    width: 200px;
    height: 400px;
    border: 5px solid;
    border-bottom-color: blue;
    border-top-color: red;
}

JS

function rotate() {
    document.getElementById("container").style.transform = 
      document.getElementById("container").style.transform === 
    "rotate(180deg)" ? "rotate(0deg)" : "rotate(180deg)";
}

Here is an example in codepen

<script>
var degrees = 0;
function rotate() {
  if(degrees == 180){
    document.getElementById("container").style.transform = 
      "rotate(360deg)";
    degrees= 0;
  }else{
    document.getElementById("container").style.transform = 
      "rotate(180deg)";
    degrees= 180;
  }       
}
</script>

Clearly is not optimized but could help you.

JSFiddle here

Others have answered your question already, so I will provide with an example to make your code a little bit more dynamic.

/**
* Rotate an <element> with a certain angle <rotateBy>
* 'this' is a reference to itself, which is passed by as an argument from the HTML.
* Change '180' in the method call to whatever to have it rotate differently.
*/

function rotate(element, rotateBy) {
  var currentRotation = element.rotation || 0;   // default to zero if not existing
      newRotation = rotateBy + currentRotation;

  element.rotation = newRotation;  // store the property in the element

  element.style.transform = "rotate(" + newRotation + "deg)";
}
.container {
    width: 200px;
    height: 400px;
    border: 5px solid;
    border-bottom-color: blue;
    border-top-color: red;

    transition: transform 400ms;
}
<div class="container" onclick="rotate(this, 180)"
></div>

    

Related