No, there is no simpler way to do this.
But, keep in mind that this is exactly why classList.add()
and classList.remove()
were added to the DOM API. Not only is there no simpler way than this already simple solution, but this is really the preferred way to handle any kind of dynamic CSS class changes that may need to occur in a page.
Just remove the transition from the baseline class and set it up in its own class and apply both classes by default. When the JS code needs to make the change (as opposed to a human), first remove the class that includes the transition, make the element change, and then add the class back (for possible human interaction later).
There is one caveat here, which is that the browser can sometimes act upon the UI faster or slower than JS can process a UI instruction so adding a slight imperceptible delay with .setTimeout()
helps the UI get updated correctly.
You can see that without a short delay built-in, the effect doesn't work:
document.querySelector("button").addEventListener("click", function(event){
const element = document.querySelector("input.transition");
// JS code is going to affect the element: remove the transition class
element.classList.remove("transition");
element.checked = !element.checked; // Toggle the UI
// Add the class back for futue possible human interaction
element.classList.add("transition");
});
* { box-sizing: border-box; }
/* This class applies all the time but does not include transition */
.switch { appearance: none; padding: 9px 18px; border-radius: 13px; background: radial-gradient(circle 9px, #007722 100%, transparent 100%) transparent -9px; border: 1px solid #007722; }
/* This class is used by default but is removed when no transition is wanted. */
.transition { transition: all .3s; }
.switch:checked { background-position: 9px; }
<div>First, change the toggle switch manually. Then, use the button to do it.</div>
<input type="checkbox" class="switch transition">
<button type="button">Click to have JS change the value</button>
But, with the delay it does:
See comments inline.
document.querySelector("button").addEventListener("click", function(event){
const element = document.querySelector("input.transition");
// JS code is going to affect the element: remove the transition class
element.classList.remove("transition");
element.checked = !element.checked; // Toggle the UI
// Adding a small delay ensures that the UI has enough time to update the UI
setTimeout(function(){
element.classList.add("transition"); // Now, add back the transition
}, .1);
});
* { box-sizing: border-box; }
/* This class applies all the time but does not include transition */
.switch { appearance: none; padding: 9px 18px; border-radius: 13px; background: radial-gradient(circle 9px, #007722 100%, transparent 100%) transparent -9px; border: 1px solid #007722; }
/* This class is used by default but is removed when no transition is wanted. */
.transition { transition: all .3s; }
.switch:checked { background-position: 9px; }
<div>First, change the toggle switch manually. Then, use the button to do it.</div>
<input type="checkbox" class="switch transition">
<button type="button">Click to have JS change the value</button>