Skip to content

Conversation

@thetaPC
Copy link
Contributor

@thetaPC thetaPC commented Oct 3, 2025

Issue number: resolves #25326


What is the current behavior?

The header flickers upon page transition when on iOS mode and using a condensed header:

Entering Page Two (P1 → P2):
When navigating to Page Two, which has a collapsing header (intended to be hidden until scroll), the header briefly flashes into view. This happens because the header is initially rendered with full opacity: 1 before the component's logic can apply opacity: 0 to hide it, causing a visible flicker.

Navigating Back (P2 → P1):
When navigating back, Page One's header briefly bleeds through the top of Page Two. Although Page Two is on top (z−index: 100), its collapsing header is set to opacity: 0. This transparency allows Page One header (z−index: 99) to become visible underneath, as the transparent area cannot block the content below it.

The header flickers upon page transition when on iOS mode and using a fade header:

Entering Page Two (P1 → P2):
When navigating to Page Two, which has a fade header (should not have a background on load), the header background briefly flashes into view. This happens because the header is initially rendered with full opacity: 1 before the component's logic can apply opacity: 0 to hide it, causing a visible flicker.

What is the new behavior?

  • Added a transition-specific class that is applied to the condensed ion-header element to override its default transparency.

This guarantees the header to act as an opaque block during the page transition, eliminating visual flickering caused by early opacity: 0 or the header underneath bleeding through.

  • Added a transition-specific class that is applied to the fade ion-header element to override its default opaque background.

This guarantees the header to act as a transparent block during the page transition, eliminating visual flickering caused by default opacity: 1.

Does this introduce a breaking change?

  • Yes
  • No

Other information

Dev build: 8.7.6-dev.11759524961.1cff6814

@vercel
Copy link

vercel bot commented Oct 3, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
ionic-framework Ready Ready Preview Comment Oct 6, 2025 4:25pm

@github-actions github-actions bot added the package: core @ionic/core package label Oct 3, 2025
* Large title toolbar should just use the content background
* since it needs to blend in with the header above it.
*/
.header-collapse-condense ion-toolbar,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the large title that is tied to the inactive header.

Comment on lines +98 to +105
.header-collapse-condense ion-toolbar,
/**
* Override styles applied during the page transition to prevent
* header flickering.
*/
.header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar {
--background: var(--ion-background-color, #fff);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I grouped these together so they will always be the same background color since they are related to the condensed header.

(result) => {
if (result.animation) {
result.animation.destroy();
const transitioningInactiveHeader = getIosIonHeader(opts);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm grabbing the header here so we don't have to do query it twice within beforeTransition and in the finally.

)
.finally(() => {
// Ensure that the header is restored to its original state.
setHeaderTransitionClass(transitioningInactiveHeader, false);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the class here since it should be removed regardless of the success of runTransition.

return;
}

const transitionClass = 'header-transitioning';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to a different name. I'm not too happy with it but not sure what else to call it to be specific.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes sense. It's added to the header during the transition.

Comment on lines +354 to +356
if (mode !== 'ios') {
return null;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see the benefit of querying out the header if the mode is md. However, we would have to update this in next to use theme instead of mode.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine with this but yeah we will need to update it eventually so that we are using the theme (or a config option for it if one is added).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific ticket I can associate it to?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No I don't think we've created tickets that far. We will just have to query for where mode is checked.

@thetaPC thetaPC changed the title fix(header): prevent flickering upon page transition on iOS fix(header): prevent flickering during iOS page transitions Oct 3, 2025
@thetaPC thetaPC marked this pull request as ready for review October 3, 2025 20:13
@thetaPC thetaPC requested a review from a team as a code owner October 3, 2025 20:13
@thetaPC thetaPC requested a review from ShaneK October 3, 2025 20:13
)
.finally(() => {
// Ensure that the header is restored to its original state.
setHeaderTransitionClass(transitioningInactiveHeader, false);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed class at the end so the header can go back to its default, preventing any potential regressions.

Copy link
Member

@brandyscarney brandyscarney left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

Comment on lines +354 to +356
if (mode !== 'ios') {
return null;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine with this but yeah we will need to update it eventually so that we are using the theme (or a config option for it if one is added).

return;
}

const transitionClass = 'header-transitioning';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes sense. It's added to the header during the transition.

@ShaneK
Copy link
Member

ShaneK commented Oct 14, 2025

Great work, Maria! Looks awesome!

@thetaPC thetaPC added this pull request to the merge queue Oct 14, 2025
Merged via the queue into main with commit 820fa28 Oct 14, 2025
51 checks passed
@thetaPC thetaPC deleted the FW-6765 branch October 14, 2025 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package: core @ionic/core package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: ios transition does not account for fade header

4 participants