Closed Bug 1859660 Opened 1 year ago Closed 4 months ago

CSS translate animation jumps back to initial position

Categories

(Core :: CSS Transitions and Animations, defect)

Firefox 118
defect

Tracking

()

VERIFIED FIXED
129 Branch
Tracking Status
firefox129 --- verified
firefox130 --- verified

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.

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.

Component: Untriaged → CSS Transitions and Animations
Product: Firefox → Core

The severity field is not set for this bug.
:jwatt, could you have a look please?

For more information, please visit BugBot documentation.

Flags: needinfo?(jwatt)

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?

Severity: -- → S3
Status: UNCONFIRMED → NEW
Ever confirmed: true
Flags: needinfo?(jwatt) → needinfo?(boris.chiou)
Attached file reduced testcase 1

Here's a reduced testcase.

STR:

  1. Load testcase.
  2. 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.

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.)

(In reply to Hiroyuki Ikezoe (:hiro) from comment #6)

Probably bug 1626165.

Yes. I suspect this is related to this bug (transition + compositor animation).

Flags: needinfo?(boris.chiou)
Depends on: 1626165

(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.

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.

(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 using translateX(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.

(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 using translateX(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).

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.

Assignee: nobody → boris.chiou
Status: NEW → ASSIGNED
Pushed by bchiou@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/65ee530c415e Compute the current value for the replaced transition running on the compositor. r=firefox-style-system-reviewers,zrhoffman
Status: ASSIGNED → RESOLVED
Closed: 4 months ago
Resolution: --- → FIXED
Target Milestone: --- → 129 Branch

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.

Status: RESOLVED → REOPENED
Resolution: FIXED → ---

Ah I see "Target Milestone: --- → 129 Branch", maybe I reopened this too hastily.

My 129.0a1 (Firefox nightly) looks good.

Status: REOPENED → RESOLVED
Closed: 4 months ago4 months ago
Resolution: --- → FIXED

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.

Status: RESOLVED → VERIFIED
Flags: qe-verify+
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: