2

Here is an example of my problem

I have an div and a button. Each time the button is clicked, the div changes it's background-color to a random color.

button.addEventListener('click', function(e){
    e.preventDefault();
    setRandomColor();
});

By default the the div has a class called transition-on which applies a transition to the background-color.

<div class="block transition-on"></div>
<button>Change</button>

CSS:

.transition-on {
  transition: background-color 0.5s
}

If I remove this class before I apply the random background-color then reapply the class after, the transition will still apply.

My intention is to remove the transition temporarily when I apply the random color.

button.addEventListener('click', function(e){
    e.preventDefault();
    block.classList.remove('transition-on');
    setRandomColor();
    block.classList.add('transition-on');
});

Does anybody know why this may be happening?

EDIT:

Referring to the answer by @ths - Using a setTimeout does produce the result that I need but now I am wondering why is it necessary to use a timeout.

Is a timeout really required to temporarily disable a css transition?

  • Remove the transition class
  • Apply the color to the block
  • Add the transition class back

This should logically change the color without a transition

Jackson
  • 3,476
  • 1
  • 19
  • 29
  • the transtion apply when you add the class again, not when your remove it – Temani Afif Aug 28 '18 at 10:40
  • @TemaniAfif But I am adding the class after I have changed the color. You should not be seeing the transition when you click the button – Jackson Aug 28 '18 at 10:55
  • As I understand, you want to change the `background-color` using `JavaScript` without seeing any transition and then add the `transition-on` class again ? – ThS Aug 28 '18 at 11:03
  • Hi @ths - Yes that is what I would like to do – Jackson Aug 28 '18 at 11:07
  • 1
    @Jackson check out my answer, it may help you. – ThS Aug 28 '18 at 11:23
  • it's after in the code, but it's on the same time when it's executed, there is no delay – Temani Afif Aug 28 '18 at 11:28
  • 1
    th e timeout is not disabling the transition, the timeout make the color change happen before you add the class, so you add a class to an elemnt with a color already changed (no transtion) .. without timeout both will happen at the same, time, you add the color and the class is there so the transiton will work – Temani Afif Aug 28 '18 at 12:15
  • 1
    @TemaniAfif - they may (not likely) or may not happen "at the same time", it is more likely the execution queue for the DOM events is a synchronous set of events perhaps? See more at https://stackoverflow.com/q/779379/125981 – Mark Schultheiss Aug 29 '18 at 12:15
  • 1
    @MarkSchultheiss I used the word *same time* because I wasn't able to express it differently because it's somehow complicated and the link you gave was one of the question I was trying to find as a duplicate ... So I guess he can know understand the complex logic behind and understand what I meant by *same time* – Temani Afif Aug 29 '18 at 12:21
  • Thanks for your input. It makes sense to me now that this is related to function execution queuing. What still bothers me is that if I set a timeout on the `classList.add` of `1ms` it has mixed results. Sometime it uses the transition and sometimes not. Perhaps the event queue works different when it needs to animate or interact with a DOM element – Jackson Aug 29 '18 at 12:43

2 Answers2

0

remove the "transition-on" class from the id="remove_trans" element:

  function changecolor()
    {
//add this code 
       var element = document.getElementById("remove_trans");

       element.classList.remove("transition-on");
        setRandomColor();
        element.classList.add('transition-on');
     }

    changecolor();

html

div id="remove_trans" class="block transition-on"></div>
<button onClick="changecolor()">Change</button>

In html tag add the id attribute

vinoth s
  • 178
  • 6
  • I fail to see how this actually answers the question of why the transition occurs. Please add DETAILED explanation perhaps with a working sample of code that shows the transition does NOT occur, and why that is the case here compared to the OP question code. – Mark Schultheiss Aug 29 '18 at 12:19
0

As I understood, you want to change the background-color dynamically using JavaScript without seeing any transition. To do so you need to put the expression that adds the transition-on class to the div element in setTimeout method and by passing the transition-duration to the second argument(in your case the transition-duration equals 0.5s).

Here's a runnable snippet to illustrate:

var block = document.querySelector('.block');
var button = document.querySelector('button');

function setRandomColor() {
  var letters = '0123456789ABCDEF';
  var color = '#';
  for (var i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  block.style.backgroundColor = color;
}

button.addEventListener('click', function(e){
  e.preventDefault();
  block.classList.remove('transition-on');
  setRandomColor();
  // the next line executes after 500 ms, thus the div element gets the transition-on class after 500 ms and no transition will happen.
  setTimeout(function() {
    block.classList.add('transition-on');
  }, 500); // 500 ms = 0.5 s => the transition-duration of the transition-on class
});
setRandomColor();
.block {
  width: 40px;
  height: 40px;
}
.transition-on {
  transition: background-color 0.5s
}
<div class="block transition-on"></div>
<button>Change</button>
ThS
  • 4,597
  • 2
  • 15
  • 27
  • Seems like a good solution but what's strange is if I change the timeout from `500ms` to `1ms`, it has the same result. Surely setting the timeout to a very small number would be the same as not putting the timeout at all. – Jackson Aug 28 '18 at 11:30
  • 1
    @Jackson but I told it must be the same as the transition duration in transition-on class ?! – ThS Aug 28 '18 at 11:32
  • 1
    @Jackson yes no need to make the same as transtion, any small value will have the same result because it's all about to delay the execution – Temani Afif Aug 28 '18 at 11:32
  • @ths The timeout in your example does not need to be the same as the transition duration. Using `1ms` in the timeout works the same as using `500ms` which doesn't explain why you need to put a timeout in the first place. – Jackson Aug 28 '18 at 11:39
  • @TemaniAfif - Why is the timeout necessary? It is a linear synchronous process. – Jackson Aug 28 '18 at 11:42
  • @Jackson the timeout is needed to delay the execution ... it's somehow tricky, but without timeout the instructions are executed at the same time for us, so the class is add at the same time when the color is changing (it doesn't matter the order in the JS) .. but the timeout will create the delay and no need to be same as transition, any delay will work because the transition will be added after the color changes in all the cases – Temani Afif Aug 28 '18 at 11:45
  • @Jackson from that I can assume you didn't digg into JavaScript. The `setTimeout` method executes a function after a delay which is the second argument. And as of the CPU is insanely fast it executes the function that changes the color in a wink so you see that setting 1 ms is the same as 500 ms, but, what's the case of the `setTimeout` method is to ensure that any function that it gets as a callback will be executed after a delay, and we have a transition-delay with that delay we assume that adding the transition-on class again will not affect the background-color change, thus no transition. – ThS Aug 28 '18 at 11:47
  • @ths because you added a *wrong* idea by saying that the delay on timeout need to be equal to the transtion which is not correct ... – Temani Afif Aug 28 '18 at 11:52
  • 1
    @TemaniAfif by that I meant to keep thing ordered, I know setting a delay less than 500 will give the same result. That's a really long story to tell about `JavaScript` and its behaviour. So to keep thing simple I said "must be the same". – ThS Aug 28 '18 at 11:55
  • @ths Do you think this is possible to do this without a timeout? – Jackson Aug 28 '18 at 11:57
  • and this what the question is about, that long story to understand the execution and how setimout affect this. by saying *must be the same* mean that if they aren't the same it won't work. – Temani Afif Aug 28 '18 at 11:58
  • @Jackson sorry but, no we can't. Only `setTimeout` method will do it. – ThS Aug 28 '18 at 11:59
  • @TemaniAfif and that's what we're discussing right now. Sometimes, we should wait the question to be asked then the benefits of the answer will affect nearly anyone who wants to know/understand/learn things. – ThS Aug 28 '18 at 12:02
  • NOTE: To redraw the element happens quickly but in order to redraw the element requires a new DOM event which is placed at the END of the queue (it is all synchronous basically) - and using a `settimeout(func,0);` re-queues to the end of that operation. Review this question for more details on this stuff: https://stackoverflow.com/q/779379/125981 – Mark Schultheiss Aug 29 '18 at 12:13
  • @MarkSchultheiss thanks for the details, I appreciate it ! – ThS Aug 29 '18 at 12:22