CSS translate animation jumps back to initial position
Categories
(Core :: CSS Transitions and Animations, defect)
Tracking
()
People
(Reporter: sspenst, Assigned: boris)
References
Details
Attachments
(4 files)
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36
Steps to reproduce:
Run the following JSFiddle in Firefox: https://jsfiddle.net/sspenst/pnLmxg8b/11/
Use the arrow keys to move the block around and back to the starting position.
Actual results:
If the block starts at translate(Xpx, Ypx) and is moved back to translate(Xpx, Ypx) before the animation has completed it will jump back to this position without animating. For example, if you press right, down, left, up the animation will be smooth until the final up press where it jumps back to (0px, 0px).
Note that this can happen from any starting position. For example, first press right and wait for the animation to complete. Now if you press right, down, left, up the block will still jump on the final up press, this time to (100px, 0px).
Expected results:
Animations should always be smooth regardless of the initial translate position. You should be able to press right, down, left, up and smoothly animate back to the initial position. I don't see this bug in Chrome or Safari.
Comment 1•1 year ago
|
||
The Bugbug bot thinks this bug should belong to the 'Core::CSS Transitions and Animations' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.
Comment 2•1 year ago
|
||
The severity field is not set for this bug.
:jwatt, could you have a look please?
For more information, please visit BugBot documentation.
Comment 3•1 year ago
|
||
I can reproduce. This has something to do with transitions being handled by the compositor. It looks like we don't properly reset transitions, if compositor animations are the only ones that are running.
I'll post a reduced testcase, which has two divs -- one of which has the transform
being transitioned, and one of which has the margin-left
being transitioned.
- If both transitions are playing at the same time, and then the style gets reset to the starting value, then both transitions play in reverse as-expected.
- BUT if only the
transform
transition is playing, and then the style gets reset to the starting value, then it just insta-snaps back to the starting transition.
boris/hiro, do you know if this is a known issue?
Comment 4•1 year ago
|
||
Here's a reduced testcase.
STR:
- Load testcase.
- Click "Begin transition"
ACTUAL RESULTS:
The teal (transformed) div slides right and then abruptly jumps back to its original position.
EXPECTED RESULT:
The teal div should transition smoothly back to its original position, rather than abruptly jumping.
Interestingly, if you click the button to show the maroon div (which has an animated margin-left instead of transform, i.e. a non-compositor transition), then we suddenly get expected results for both of the transitions (the transform one as well as the margin-left one) -- they both transition smoothly back to their original position.
Comment 5•1 year ago
|
||
Here's a testcase where the transition just plays automatically (and snaps abruptly back to the start position each time).
One important note: to repro reliably, do not hover the div with your mouse. If I do hover the area where the div is oscillating, then I tend to get expected-results, some of the time at least. (And as with the other testcase: if I click the button to show the other div with the margin transition, then I get expected-results too.)
Comment 6•1 year ago
|
||
Probably bug 1626165.
Assignee | ||
Comment 7•1 year ago
|
||
(In reply to Hiroyuki Ikezoe (:hiro) from comment #6)
Probably bug 1626165.
Yes. I suspect this is related to this bug (transition + compositor animation).
Assignee | ||
Comment 8•1 year ago
|
||
(In reply to Daniel Holbert [:dholbert] from comment #5)
One important note: to repro reliably, do not hover the div with your mouse.
Yes. Hovering the div with the mouse may sync the transition on the main thread. This is definitely a compositor animation issue.
Assignee | ||
Comment 9•5 months ago
•
|
||
I suspect we didn't throttle the animation when calling reset()
(e.g. perhaps something wrong in PreTraverse or other places), so the before-change style is still using translateX(0px)
, instead of the transform value with the running transition, e.g. translateX(123px)
. Therefore, we don't create any reversing transition at the moment.
This looks like a regression because this is a basic case which should be passed when implementing compositor animations.
Probably not related to bug 1626165 because the main thread is not busy in this bug, and we didn't even try to create any transitions.
Comment 10•5 months ago
|
||
(In reply to Boris Chiou [:boris] from comment #9)
I suspect we didn't throttle the animation when calling
reset()
(e.g. perhaps something wrong in PreTraverse or other places), so the before-change style is still usingtranslateX(0px)
, instead of the transform value with the running transition, e.g.translate(123px)
. Therefore, we don't create any reversing transition at the moment.
I suppose you meant "we don't unthrottle", right? But how and when? The reset()
function does change the transform style in question, thus the element will be traversed in the first normal style traversal (so that it will trigger a CSS transform transition). But if we do unthrottle the animation before the first traversal, it does mean the compositor running animation runs on the main-thread too.
Bug 1626165 will introduce a way to avoid this situation.
Assignee | ||
Comment 11•5 months ago
|
||
(In reply to Hiroyuki Ikezoe (:hiro) from comment #10)
(In reply to Boris Chiou [:boris] from comment #9)
I suspect we didn't throttle the animation when calling
reset()
(e.g. perhaps something wrong in PreTraverse or other places), so the before-change style is still usingtranslateX(0px)
, instead of the transform value with the running transition, e.g.translate(123px)
. Therefore, we don't create any reversing transition at the moment.I suppose you meant "we don't unthrottle", right? But how and when? The
reset()
function does change the transform style in question, thus the element will be traversed in the first normal style traversal (so that it will trigger a CSS transform transition). But if we do unthrottle the animation before the first traversal, it does mean the compositor running animation runs on the main-thread too.Bug 1626165 will introduce a way to avoid this situation.
Oh yes. I meant "we don't unthrottle". The normal style traversal doesn't trigger a CSS transform transition because the transform value of before-change style is still translateX(0)
. For example, the old_value
and new_value
in Servo_ComputedValues_ShouldTransition
are both translateX(0px)
after the normal style traversal, so we don't create any transition.
I'm still debugging this, and trying to figure out why the before-change style is 0px
instead of 400px
. (I thought it should be 123px
with transition rule but actually we don't compose the style on the main thread so it should be 400px
in this case I guess).
Assignee | ||
Comment 12•5 months ago
|
||
We rely on the current value to check if we have to create a transition
to replace the running one, and if the running transition is on the
compositor, we don't have the up-do-date transition rule on the main
thread, so we have to compute it when trying to create a new transition.
Updated•5 months ago
|
Comment 13•4 months ago
|
||
Comment 14•4 months ago
|
||
bugherder |
Reporter | ||
Comment 15•4 months ago
|
||
Daniel Holbert's reduced cases seem to work now, however I am still seeing the same issue with my original JSFiddle using Firefox 127.0.2.
Reporter | ||
Comment 16•4 months ago
|
||
Ah I see "Target Milestone: --- → 129 Branch", maybe I reopened this too hastily.
Assignee | ||
Comment 17•4 months ago
|
||
My 129.0a1 (Firefox nightly) looks good.
Updated•4 months ago
|
Comment 18•4 months ago
|
||
Reproducible on Firefox 128.0 on macOS 14 using the testcases from Comment 4 and 5.
Verified as fixed on Firefox 129.0b2 and Firefox Nightly 130.0a1 on macOS 14, Ubuntu 22, Windows 10.
Description
•