Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS transition-delay with a negative value?

I am trying to understand negative values for the CSS transition-delay property. Please look at the code example first. There are two divs which have different transition delays.

I thought giving the negative value for the delay would be the same as giving a positive value to right div (0.2s) but it is not behaving the same. I think it does not paint for 0.2s which makes transition jumpy.

  • Can anyone explain me what does negative transition-delay value do?
  • Is a negative value for transition-delay valid, or should they not be used?
  • If it is alright to use them, what is a good use case?

function toggle() {
  var left = document.querySelector('.left');
  var right = document.querySelector('.right');
  left.classList.toggle('hidden');
  right.classList.toggle('hidden');
  left.classList.toggle('show');
  right.classList.toggle('show');
}
window.setInterval(toggle, 1500);
window.setTimeout(toggle, 100);
#container {
  background: yellow;
  display: flex;
  width: 200px;
  height: 200px;
  overflow: hidden;
}
.left,
.right {
  flex: 1;
}
.left {
  background: red;
  transition: transform 1s -0.2s cubic-bezier(0.19, 1, 0.22, 1);
}
.right {
  background: blue;
  transition: transform 1s cubic-bezier(0.19, 1, 0.22, 1);
}
.hidden {
  transform: translateY(100%);
}
.show {
  transform: translateY(0%);
}
.container-hide {
  transform: translateY(-100%);
}
<div id="container">
  <div class="left hidden"></div>
  <div class="right hidden"></div>
</div>
like image 365
fiddlest Avatar asked Jan 02 '17 19:01

fiddlest


2 Answers

A negative transition-delay is actually completely valid, and it has a different meaning that 0s and is not the same as a positive delay.

Excerpt from W3C Working Draft for transition-delay:

If the value for transition-delay is a negative time offset then the transition will execute the moment the property is changed, but will appear to have begun execution at the specified offset. That is, the transition will appear to begin part-way through its play cycle. In the case where a transition has implied starting values and a negative transition-delay, the starting values are taken from the moment the property is changed.

The result is that the the first part of the animation will be skipped. Basically, the start time is shifted, changing the computed point on the animation.

So if a 10s duration animation has a -5s delay, it will appear to start half-way in (skipping the first half), and complete in only 5s. Here is a simple example to show this effect in action.

Illustrative Example:

function toggle() {
  var left = document.querySelector('.left');
  var right = document.querySelector('.right');
  left.classList.toggle('hidden');
  right.classList.toggle('hidden');
  left.classList.toggle('show');
  right.classList.toggle('show');
}
window.setInterval(toggle, 15000);
window.setTimeout(toggle, 100);
#container {
  background: yellow;
  display: flex;
  width: 200px;
  height: 200px;
  overflow: hidden;
}
.left,
.right {
  flex: 1;
}
.left {
  background: red;
  transition: transform 10s linear;
  transition-delay: -5s;
}
.right {
  background: blue;
  transition: transform 10s linear;
  transition-delay: 0s;
}
.hidden {
  transform: translateY(100%);
}
.show {
  transform: translateY(0%);
}
.container-hide {
  transform: translateY(-100%);
}
<div id="container">
  <div class="left hidden"></div>
  <div class="right hidden"></div>
</div>

There isn't really any reason to necessarily avoid using negative duration values, as they are valid, they just have a very limited use case.

like image 131
Alexander O'Mara Avatar answered Oct 23 '22 16:10

Alexander O'Mara


Q: Can anyone explain me what does negative transition-delay value do?

Per the MDN documentation for the transition-delay:

Negative values cause the transition to begin immediately, but to cause the transition to seem to begin partway through the animation effect.

This is also described in the W3C Working Draft for the property, as mentioned by Alexander O' Mara's answer:

If the value for transition-delay is a negative time offset then the transition will execute the moment the property is changed, but will appear to have begun execution at the specified offset. That is, the transition will appear to begin part-way through its play cycle. In the case where a transition has implied starting values and a negative transition-delay, the starting values are taken from the moment the property is changed.

This means the transition will start immediately and partway through, as if the specified time had already gone by. For example, consider this (open snippet):

#box1 {
  width: 200px;
  height: 50px;
  
  transition: width 3s 1s;
    
  background-color: green;
}

#box2 {
  width: 200px;
  height: 50px;
  
  transition: width 3s 0s;
    
  background-color: red;
}

#box3 {
  width: 200px;
  height: 50px;
  
  transition: width 3s -1s;
    
  background-color: blue;
}


#box1:hover, #box2:hover, #box3:hover {
  width: 400px;
}
<div id="box1"></div>
<div id="box2"></div>
<div id="box3"></div>

<ul>
  <li>Box 1 (green) has transition delay of 1s.</li>
  <li>Box 2 (red) has transition delay of 0s.</li>
  <li>Box 3 (blue) has transition delay of -1s.</li>
<ul>  

You can see that the blue box (the one with transition delay of -1s) is a bit jumpy. This is because the transition starts immediately, and starts partway through the transition, as if 1 second has passed since the transition should've started.

Basically, negative values for property transition-delay make the transition start at where the transition would have been after |x| (absolute value of x) time, where x is the specified value of the property. So if we specify -1s for the delay, the transition will start immediately, and will start where the transition would've been at 1s in. Negative values also take away from the duration of the transition.


Q: Is a negative value for transition-delay valid, or should they not be used?

They are absolutely valid, and has been valid since the first Working Draft of CSS Transitions. The property allows all values of time, and allowing negative values is a consequence of that.

Because of the defined behavior of transition-delay to delay a transition by a certain offset, negative values follow that by offsetting by a negative value. That, in turn, leads to animations starting partway through, as if the absolute value of the specified time had already passed.


Q: If it is alright to use them, what is a good use case?

It's hard to outline a concrete usecase for such the effect as it's not often used and is very limited in use. I suppose potential a potential use could be reusing the transition by jumping to different states during the transition cycle.

The above is especially true when you use animations, contrary to transitions as they are repeating. When you use animations, negative delays can allow you to jump to certain points of the animation and allow reuse-ability across multiple elements that share behavior, just not timing. Take the example below (found here):

div {
  border-radius:50%;
  position:absolute;
  top:50%; left:75%;
}
div:nth-of-type(odd) { background:black; }
div:nth-of-type(even) { background:white; border:2px solid black; }
div:nth-of-type(11) {
  height:10px; width:10px;
  margin-top:-5px; margin-left:-5px;
  -webkit-animation:slide 3s ease-in-out infinite;
  animation:slide 3s ease-in-out infinite;
}
div:nth-of-type(10) {
  height:20px; width:20px;
  margin-top:-12px; margin-left:-12px;
  -webkit-animation:slide 3s -2.7s ease-in-out infinite;
  animation:slide 3s -2.7s ease-in-out infinite;
}
div:nth-of-type(9) {
  height:40px; width:40px;
  margin-top:-20px; margin-left:-20px;
  -webkit-animation:slide 3s -2.4s ease-in-out infinite;
  animation:slide 3s -2.4s ease-in-out infinite;
}
div:nth-of-type(8) {
  height:60px; width:60px;
  margin-top:-32px; margin-left:-32px;
  -webkit-animation:slide 3s -2.1s ease-in-out infinite;
  animation:slide 3s -2.1s ease-in-out infinite;
}
div:nth-of-type(7) {
  height:80px; width:80px;
  margin-top:-40px; margin-left:-40px;
  -webkit-animation:slide 3s -1.8s ease-in-out infinite;
  animation:slide 3s -1.8s ease-in-out infinite;
}
div:nth-of-type(6) {
  height:100px; width:100px;
  margin-top:-52px; margin-left:-52px;
  -webkit-animation:slide 3s -1.5s ease-in-out infinite;
  animation:slide 3s -1.5s ease-in-out infinite;
}
div:nth-of-type(5) {
  height:120px; width:120px;
  margin-top:-60px; margin-left:-60px;
  -webkit-animation:slide 3s -1.2s ease-in-out infinite;
  animation:slide 3s -1.2s ease-in-out infinite;
}
div:nth-of-type(4) {
  height:140px; width:140px;
  margin-top:-72px; margin-left:-72px;
  -webkit-animation:slide 3s -0.9s ease-in-out infinite;
  animation:slide 3s -0.9s ease-in-out infinite;
}
div:nth-of-type(3) {
  height:160px; width:160px;
  margin-top:-80px; margin-left:-80px;
  -webkit-animation:slide 3s -0.6s ease-in-out infinite;
  animation:slide 3s -0.6s ease-in-out infinite;
}
div:nth-of-type(2) {
  height:180px; width:180px;
  margin-top:-92px; margin-left:-92px;
  -webkit-animation:slide 3s -0.3s ease-in-out infinite;
  animation:slide 3s -0.3s ease-in-out infinite;
}
div:nth-of-type(1) {
  height:200px; width:200px;
  margin-top:-100px; margin-left:-100px;
  -webkit-animation:slide 3s ease-in-out infinite;
  animation:slide 3s ease-in-out infinite;
}
@keyframes slide {
  0% { left:75% }
  50% { left:25%; }
  100% { left:75%; }
}
@-webkit-keyframes slide {
  0% { left:75% }
  50% { left:25%; }
  100% { left:75%; }
}
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>

Here, negative animation-delay values are utilized by jumping to different states in the animation cycle. All the circles share the same behavior, by going back and forth, but different timing, as they simulate a wave. Negative animation-delay makes the circles move at different times, further into the animation cycle.

like image 7
Andrew Li Avatar answered Oct 23 '22 15:10

Andrew Li