Skip to content

bug: applyFullscreenSafeArea() shrinks fullscreen modal wrapper when ion-content exists without ion-footer (8.8.1 regression) #31015

Closed

Description

@a-hazaiti

Prerequisites

Ionic Framework Version

v8.x (8.8.1)

Current Behavior

After upgrading from @ionic/angular 8.7.17 to 8.8.1, fullscreen modals (presented via ModalController with cssClass: "fullscreen") that contain ion-content but no ion-footer display a white gap at the bottom on iOS devices with a home indicator (safe area).

This is caused by the new applyFullscreenSafeArea() method in modal.tsx (introduced in PR #30949, included in 8.8.1). The method contains this logic:

let hasContent = false;
let hasFooter = false;
for (const child of Array.from(el.children)) {
  if (child.tagName === 'ION-CONTENT') hasContent = true;
  if (child.tagName === 'ION-FOOTER') hasFooter = true;
  for (const grandchild of Array.from(child.children)) {
    if (grandchild.tagName === 'ION-CONTENT') hasContent = true;
    if (grandchild.tagName === 'ION-FOOTER') hasFooter = true;
  }
}

if (!hasContent || hasFooter) return;

wrapperEl.style.setProperty('height', 'calc(var(--height) - var(--ion-safe-area-bottom, 0px))');
wrapperEl.style.setProperty('padding-bottom', 'var(--ion-safe-area-bottom, 0px)');

When ion-content is present without ion-footer, the wrapper height is reduced by --ion-safe-area-bottom and equivalent padding is added. This creates a visible white gap at the bottom of the modal because the flex content area shrinks but the modal's visual boundary doesn't move.

This is a regression — the same templates worked correctly on 8.7.17.

Expected Behavior

Fullscreen modals with ion-content and no ion-footer should render identically to how they did in 8.7.x — filling the entire screen without a gap at the bottom. The content inside ion-content already handles its own safe-area padding via --ion-safe-area-bottom on the scroll container. Applying it a second time at the wrapper level causes double safe-area compensation.

Steps to Reproduce

  1. Create an Ionic Angular app with @ionic/angular 8.8.1
  2. Create a modal component with this template:
<ion-header>
  <ion-toolbar>
    <ion-title>Modal Title</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <p>Some content here</p>
</ion-content>

<!-- No ion-footer -->
  1. Present it as a fullscreen modal:
const modal = await this.modalCtrl.create({
  component: MyModalComponent,
  cssClass: 'fullscreen'
});
await modal.present();
  1. Run on an iOS device/simulator with a home indicator (iPhone X or later)
  2. Observe a white gap at the bottom of the modal

Code Reproduction URL

Reproduction project can be provided upon request.

Ionic Info

Ionic:
   Ionic CLI       : 7.2.1
   Ionic Framework : @ionic/angular 8.8.1
   @angular/cli    : 21.3.1
   @ionic/angular-toolkit : 12.3.0

Capacitor:
   Capacitor CLI      : 8.1.0
   @capacitor/android : 8.1.0
   @capacitor/core    : 8.1.0
   @capacitor/ios     : 8.1.0

System:
   NodeJS : v22.17.0
   npm    : 10.9.2
   OS     : macOS

Additional Information

Root cause: PR #30949 (resolving #28411 and #30900) added applyFullscreenSafeArea() to handle safe-area insets dynamically for modals. The heuristic if (!hasContent || hasFooter) return; assumes that any modal with ion-content and no ion-footer needs wrapper-level safe-area compensation. However, ion-content already handles bottom safe-area internally via its scroll container, so this creates a double safe-area effect.

Affected templates: Any modal that uses ion-content without ion-footer — a very common pattern for settings modals, info modals, selection modals, etc.

Current workaround: Add an empty <ion-footer></ion-footer> after </ion-content> in the modal template. This triggers the hasFooter early-exit path, preventing the wrapper height reduction:

<ion-content>
  <!-- modal content -->
</ion-content>

<!-- Workaround: empty ion-footer prevents applyFullscreenSafeArea() regression -->
<ion-footer></ion-footer>

Suggested fix considerations:

  • ion-content already applies --ion-safe-area-bottom to its scroll padding. The wrapper-level adjustment creates double compensation.
  • Consider only applying the wrapper adjustment when the modal does NOT contain ion-content (raw HTML modals), or when ion-content has fullscreen="false", rather than when ion-footer is absent.
  • Alternatively, check whether the modal's --height is 100% (fullscreen) before reducing it.

Activity

  1. ionitron-bot commented on Mar 18, 2026

    @ionitron-bot

    Thanks for the issue! This issue has been labeled as needs reproduction. This label is added to issues that need a code reproduction.

    Please reproduce this issue in an Ionic starter application and provide a way for us to access it (GitHub repo, StackBlitz, etc). Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.

    If you have already provided a code snippet and are seeing this message, it is likely that the code snippet was not enough for our team to reproduce the issue.

    For a guide on how to create a good reproduction, see our Contributing Guide.

  2. a-hazaiti commented on Mar 19, 2026

    @a-hazaiti
    Author

    Hi — here's a minimal reproduction repo:

    https://github.com/a-hazaiti/ionic-8.8-modal-safe-area-repro

    Quick setup

    git clone https://github.com/a-hazaiti/ionic-8.8-modal-safe-area-repro.git
    cd ionic-8.8-modal-safe-area-repro
    npm install
    npx cap add ios
    ionic build
    npx cap sync ios
    npx cap open ios

    Run on a notched iPhone simulator (iPhone 15/16).

    What to test

    The home page has two buttons:

    1. "Open Buggy Modal (no ion-footer)" — Opens a fullscreen modal with ion-header + ion-content (30 list items + red notice text at bottom), but no ion-footer. The modal wrapper height is reduced by safe-area-inset-bottom, clipping the bottom content.

    2. "Open Fixed Modal (empty ion-footer)" — Same modal but with an empty <ion-footer></ion-footer>. This triggers the early return in applyFullscreenSafeArea() and the modal displays at full height.

    Versions

    Package Version
    @ionic/angular 8.8.1
    @ionic/core 8.8.1
    @angular/core 20.x
    @capacitor/core 8.2.0

    The README in the repo includes a full root cause analysis tracing the issue to the applyFullscreenSafeArea() method in modal.tsx (introduced in PR #30949).

  3. added
    type: buga confirmed bug report
    and removed on Mar 19, 2026
  4. ionitron-bot commented on Mar 30, 2026

    @ionitron-bot

    This issue has been labeled as help wanted. This label is added to issues that we believe would be good for contributors.

    If you'd like to work on this issue, please comment here letting us know that you would like to submit a pull request for it. This helps us to keep track of the pull request and make sure there isn't duplicated effort.

    For a guide on how to create a pull request and test this project locally to see your changes, see our contributing documentation.

    Thank you!

  5. robingenz commented on Apr 13, 2026

    @robingenz
    Contributor

    We ran into this issue after upgrading from @ionic/core@^8.2.2 to 8.8.3. The applyFullscreenSafeArea() method shrinks the modal wrapper by the safe area bottom inset after the opening animation completes, causing a visible jump on iOS for all fullscreen modals that have ion-content but no ion-footer.

    As a temporary workaround, we're using the following CSS override to undo the inline styles set by applyFullscreenSafeArea():

    ion-modal::part(content) {
      height: var(--height) !important;
      padding-bottom: 0 !important;
    }
  6. ShaneK commented on Apr 22, 2026

    @ShaneK
    Member

    I have a dev build up to address this issue, please try it out and let me know if it improves things for you if you have the time:

    8.8.5-dev.11776879142.101200b9
    
  7. robingenz commented on Apr 27, 2026

    @robingenz
    Contributor

    I have a dev build up to address this issue, please try it out and let me know if it improves things for you if you have the time:

    8.8.5-dev.11776879142.101200b9
    

    I can confirm that the issue has been resolved in this build

  8. added a commit that references this issue on Apr 27, 2026
    f3cd39b
  9. ShaneK commented on Apr 29, 2026

    @ShaneK
    Member

    The fix for this has been released in v8.8.5!

  10. ionitron-bot commented on May 29, 2026

    @ionitron-bot

    Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

  11. locked and limited conversation to collaborators on May 29, 2026
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

    help wanteda good issue for the communitypackage: angular@ionic/angular packagetype: buga confirmed bug report

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions