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
Skip to content

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

Closed as not planned

Description

@tzdevelopteam

Ionic Framework Version

v9.x (@ionic/core 9.0.7, @ionic/angular 9.0.7)

Current Behavior

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:

  1. 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;
  2. then afterTransition() and the promise resolves;
  3. @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

  1. Angular app, two routed pages A → B, B has a back button.
  2. Navigate forward to B, then back. Record the screen (or hook requestAnimationFrame and sample getComputedStyle(leavingEl).opacity once the transition promise resolves).
  3. After the exit animation reaches opacity 0, the leaving element is at opacity 1 for one frame before it is detached.

Ionic Info

@ionic/core 9.0.7, @ionic/angular 9.0.7, Angular 22.

Activity

  1. thetaPC commented on Oct 23, 2026

    @thetaPC
    Contributor

    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: 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:

    import { createAnimation, provideIonicAngular } from '@ionic/angular';
    import type { AnimationBuilder } from '@ionic/angular';
    
    export const fadeAnimation: AnimationBuilder = (_baseEl, opts) => {
      const leaving = createAnimation().addElement(opts.leavingEl).fromTo('opacity', 1, 0);
    
      return createAnimation()
        .addElement(opts.enteringEl)
        .duration(200)
        .fill('both')
        .beforeRemoveClass('ion-page-invisible')
        .addAnimation(leaving)
        .onFinish((currentStep) => {
          if (currentStep === 1 && opts.direction === 'back') {
            opts.leavingEl.style.setProperty('display', 'none');
          }
        });
    };
    
    // app.config.ts
    provideIonicAngular({ navAnimation: fadeAnimation });

    Closing this, since the default transitions already hide the leaving page before its animation is removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions