ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.08k stars 13.51k forks source link

bug: Content in menu does not respect safe area #19482

Closed mhartington closed 1 year ago

mhartington commented 5 years ago

Bug Report

Ionic version:

[x] 4.x

Current behavior:

When placing an ion-content as a direct child of ion-menu on iOS, the content area is pushed up into the statusbar area.

Expected behavior:

The content should be pushed down by the safe-area amount.

Steps to reproduce:

Related code:

<ion-app>
  <div class="ion-page" id="main"></div>
  <ion-menu contentId="main">

    <ion-content>
      <ion-list>
        <ion-item>Item 01</ion-item>
        <ion-item>Item 02</ion-item>
        <ion-item>Item 03</ion-item>
      </ion-list>
    </ion-content>
  </ion-menu>
</ion-app>

IMG_9823

hkjeffchan commented 5 years ago

same as ionic3 on IOS13

aparajita commented 4 years ago

Hey @mhartington, I fixed this issue with this CSS:

/*
  Push the top of the menu below the safe area
  so it doesn't overlay the status bar
*/
ion-menu {
  margin-top: env(safe-area-inset-top);
}

/*
  Pull the menu header up to account for the menu top margin
*/
ion-menu ion-header:first-child,
ion-menu ion-content:first-child {
  margin-top: calc(env(safe-area-inset-top) * -1);
}
basvdijk commented 3 years ago

Hey @mhartington, I fixed this issue with this CSS:

/*
  Push the top of the menu below the safe area
  so it doesn't overlay the status bar
*/
ion-menu {
  margin-top: env(safe-area-inset-top);
}

/*
  Pull the menu header up to account for the menu top margin
*/
ion-menu ion-header:first-child,
ion-menu ion-content:first-child {
  margin-top: calc(env(safe-area-inset-top) * -1);
}

@aparajita Thanks for providing a solution. I needed to do some tweaking to make it work for my app:

ion-menu {
  margin-top: env(safe-area-inset-top);
}

ion-menu ion-content {
  margin-top: calc(env(safe-area-inset-top) * -1) !important;
}
paolosanchi commented 3 years ago

it seems that the safe area is set only for toolbar in header and footer:

https://github.com/ionic-team/ionic-framework/blob/f81d18c6f9f1bce056afda1cac4cf6d6ace0a7ca/core/src/components/header/header.scss#L17-L19 https://github.com/ionic-team/ionic-framework/blob/f81d18c6f9f1bce056afda1cac4cf6d6ace0a7ca/core/src/components/footer/footer.scss#L17-L19

So the supposed way to do it is this one:

<ion-app>
  <ion-menu contentId="main">
    <ion-header>
        <ion-toolbar>
            {stuff}
        </ion-toolbar>
    </ion-header>
    <ion-content>
            {stuff}
    </ion-content>
    <ion-footer>
        <ion-toolbar>
            {stuff}
        </ion-toolbar>
    </ion-footer>
  </ion-menu>
</ion-app>

I know you are aware, I type this down if anyone struggle on this like I did.

Behind this, I think the guys at ionic seems to use dedicated variables instead of directly safe-area-inset-top, probably for testing propose. https://github.com/ionic-team/ionic-framework/blob/f81d18c6f9f1bce056afda1cac4cf6d6ace0a7ca/core/src/css/core.scss#L149-L156 Actually, you can redefine them in index.html like this: https://github.com/ionic-team/ionic-framework/blob/a9b22601008b36c2c2f10129d20be6e3cdc4f336/core/src/components/modal/test/basic/index.html#L13-L20

SaroGFX commented 2 years ago

I have spend countless hours now on trying to get this right. But the toolbar keeps getting screwing up in the menu. I tried a rebuild like above is done, but I still get bugged results.

<IonMenu 
      contentId="main" 
      swipeGesture={true} 
      disabled={isDisabled()}
      className={MenuCSS.Menu}
    >

      <IonHeader>
        <IonToolbar><IonTitle>Title</IonTitle></IonToolbar>
      </IonHeader>

      <nav>
        <IonText>Administration</IonText>
        <ul>
          <li>item</li>
          <li>item</li>
          <li>item</li>
          <li>item</li>
          <li>item</li>
          <li>item</li>
          <li>item</li>
          <li>last item</li>
        </ul>
      `</nav>`

      <footer>
        <IonText>Footer</IonText>
      </footer>
    </IonMenu>
ion-menu.Menu {
    --background: var(--wf-dark-gray);

    &::part(container) {
        justify-content: start;
    }

    nav {
        overflow-y: auto;
    }

    footer {
        margin-top: auto;
        background-color: rgba(var(--ion-color-white-rgb), 0.2);
        padding: 1em;
    }

}

The result on iPhone 13

Screenshot 2022-06-01 at 13 42 46

eugr commented 1 year ago

Looks like this bug has been open for 5 years already! Are there any plans to fix?

thetaPC commented 1 year ago

PR https://github.com/ionic-team/ionic-docs/pull/3102 does not fix this issue. This will be revisited at a later time.

thetaPC commented 1 year ago

Thank you for the issue!

When it comes to safe area, ion-content will not automatically apply padding to any of its sides to account for the safe area. This is because the content component is often used in conjunction with other components that apply their own padding, such as headers and footers. However, if the content component is being used on its own, it may be desired to apply padding to the safe area.

In this case, a solution is to apply the padding directly to prevent any content from being rendered in the status bar.

ion-menu ion-content::part(scroll) {
  padding-top: var(--ion-safe-area-top, 0);
}

or you can target ion-menu directly

ion-menu::part(container) {
  padding-top: var(--ion-safe-area-top, 0);
}

You can read more about safe area padding at the docs page.

Thank you!

ionitron-bot[bot] commented 11 months ago

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.