bug(angular): the leaving page is painted fully visible for one frame at the end of a back transition — its animation is destroyed one requestAnimationFrame before the stack controller hides it · Issue #31599 · ionic-team/ionic-framework · GitHub
You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
bug(angular): the leaving page is painted fully visible for one frame at the end of a back transition — its animation is destroyed one requestAnimationFrame before the stack controller hides it #31599
On a back navigation the leaving page sits above the entering one (core/src/utils/transition/index.ts L286–295, setZIndex: leaving z-index: 101, entering 100) and animates out (opacity / transform). When the animation finishes:
transition() (utils/transition/index.ts L29–45) calls result.animation.destroy() — cleanUpElements() (utils/animation/animation.ts L191–199) cancels the Web Animations, which drops their fill: both end state; the leaving page snaps back to opacity 1 / transform none while still on top;
then afterTransition() and the promise resolves;
@ionic/angular's StackController.setActive continues .then(() => cleanupAsync(...)) (dist/common/directives/navigation/stack-controller.js L113–114), and cleanupAsync (L245–255) waits for a requestAnimationFrame before cleanup destroys the popped view / adds ion-page-hidden (L258–280).
Between 1 and 3 there is at least one rendered frame in which the page the user just left is painted in full on top of the page they navigated back to.
Expected Behavior
The leaving page is hidden or removed before its exit animation's end state is dropped, so the back navigation ends on the entering page without a flash.
Steps to Reproduce
Angular app, two routed pages A → B, B has a back button.
Navigate forward to B, then back. Record the screen (or hook requestAnimationFrame and sample getComputedStyle(leavingEl).opacity once the transition promise resolves).
After the exit animation reaches opacity 0, the leaving element is at opacity 1 for one frame before it is detached.
Verified on 9.0.9. The default md and ios back transitions don't paint the frame described here. Each one sets display: none on the leaving page in its finish hook, and that hook runs before the transition promise resolves, so the leaving page is already hidden when destroy() cancels its animations and during the frame cleanupAsync waits. Sampling getComputedStyle(leavingEl).opacity at that point does return 1, but display: none doesn't change computed opacity, so that probe reports a flash that isn't painted. Checking display in the same frame shows none.
The frame only appears with a custom animation or navAnimation that fades the leaving page out without hiding it. If that's your setup, hide the leaving page when a back transition completes, the same way the built-in transitions do:
Activity
thetaPC commentedon Oct 23, 2026
Thanks for the report!
Verified on 9.0.9. The default md and ios back transitions don't paint the frame described here. Each one sets
display: noneon the leaving page in its finish hook, and that hook runs before the transition promise resolves, so the leaving page is already hidden whendestroy()cancels its animations and during the framecleanupAsyncwaits. SamplinggetComputedStyle(leavingEl).opacityat that point does return1, butdisplay: nonedoesn't change computed opacity, so that probe reports a flash that isn't painted. Checkingdisplayin the same frame showsnone.The frame only appears with a custom
animationornavAnimationthat fades the leaving page out without hiding it. If that's your setup, hide the leaving page when a back transition completes, the same way the built-in transitions do:Closing this, since the default transitions already hide the leaving page before its animation is removed.