Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS transformation change during transition causes current state to get lost and jumps to the beginning (Chrome bug)

Tested in Google Chrome 73 (Official Build) (64-bit).

Also tested in latest stable Mozilla, Opera and Safari.

Looks like it is a bug of Chrome only. Hope there is a workaround until the Chrome team fix the bug.

Demo

I have created Codepen to show the problem.

const div = document.querySelector('div');

const cssTransition = 2500;
const states = [
  ['INITIAL', 'translate(0)', cssTransition / 2],
  ['A', 'translate(0, 100px)', cssTransition + 500],
  ['B', 'translate(100px, 100px)', cssTransition / 2],
];

let cursor = 0;

const animate = () => {
  cursor = (cursor + 1) % states.length;
  const [name, value, delay] = states[cursor];
  setTimeout(() => {
    div.innerText = name;
    div.style.transform = value;
    animate();
  }, delay);
};

animate();
div {
  width: 100px;
  height: 100px;
  background: brown;
  color: white;
  font-size: 25px;
  font-family: sans-serif;
  text-align: center;
  line-height: 100px;
  margin: 50px auto;
  transition: 2.5s ease;
}
<div>INITIAL</div>

Task

Animate element via JavaScript to change its position on the screen using CSS3 transform property.

Conditions:

  1. Element has fixed transition time (defined in CSS file).
  2. At any time of animation JavaScript may set new position of element might i.e. change will happen before existing animation finished.
  3. New position of element is not known in advance => i.e. list of CSS classes is not an option here.

The problem is - transition is not smooth because new animation jumps from initial position of previous animation instead of smooth transition from current location.

Actual behavior

When CSS transform property of an element is changed during transition (i.e. before current animation finished) the next animation starts from the initial state of previous animation.

wrong, jumpy css transition

  • steps 1-5 is first animation (transition between INITIAL and A states).
  • steps 6-10 is second animation (transition between INITIAL and B states).
  • step 3 is where first animation got interrupted because final transform property changed i.e. second animation starts here.

As you can see, animation jumps to INITIAL state which is wrong (undesired). Position at step 6 should be near step 3.

Expected behavior

CSS transform property change should reset internal animation timer to 0 (so, new animation will last as defined in transition property) but keep current transform state as initial state for the next animation.

proper, expected css transition

  • steps 1-5 is first animation (transition between INITIAL and A states).
  • steps 6-10 is second animation (transition between intermediate "INITIAL to A" and B states).
  • step 3 is where first animation got interrupted because final transform property changed i.e. second animation starts here.

As you can see, new animation starts exactly where it is expected - from step 3 and nicely move element to the new position.

Thanks for reading. Looking forward for your help.

like image 448
Oleksii Shnyra Avatar asked Apr 12 '19 07:04

Oleksii Shnyra


People also ask

What is the difference between transition and transform in CSS?

So, what's the difference between CSS Transform and CSS Transition? The Transform property in CSS moves or modifies the appearance of an element, whereas the Transition property seamlessly and gently transitions the element from one state to another.

How do you change the transition direction in CSS?

It works as follows: The overlay resting state is set to the right of the element using a margin (while the left is positioned to the left of the element). Upon hover, we set the margin to 0 without an animation. This allows the left animation to occur from the left side of the element.

How do you stop a transition in CSS?

To trigger an element's transition, toggle a class name on that element that triggers it. To pause an element's transition, use getComputedStyle and getPropertyValue at the point in the transition you want to pause it. Then set those CSS properties of that element equal to those values you just got.

What is a transform in CSS?

The transform CSS property lets you rotate, scale, skew, or translate an element. It modifies the coordinate space of the CSS visual formatting model.


1 Answers

I am unsure why it happens but a solution would be to manually set the transitioned property (here transform) to its currently computed value, right before changing to the new desired one.

div.style.transform = getComputedStyle(div).transform;
// Cause a reflow to force the browser to apply the set transform
div.innerWidth;
div.style.transform = value;

Here is a fork of your pen including the fix.

getComputedStyle is widely supported so you don't need to worry about a polyfill unless you want to support IE < 9

like image 122
Bali Balo Avatar answered Oct 16 '22 09:10

Bali Balo