Safe Area Values Always Zero on Android with Ionic Capacitor Version 6

Hello,

I recently set up a project using Ionic with Capacitor version 6, and I’ve encountered an issue where the safe area values on Android are consistently returning zero. I’m currently on Android 14, using Java 17, and Gradle 8.6. However, everything works perfectly on iOS.

Could anyone provide insights or solutions to this issue?

Thank you!

Check this discussion - SOLVED -–ion-safe-area has no effect on iOS

Make sure your <meta name="viewport" is correct.

It must be correct since it was created by Ionic, but just in case, I’ll paste it here for you.

    <meta
      name="viewport"
      content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
    />

Here is the solution I’d like to share:

npm install capacitor-plugin-safe-area

import { SafeArea } from "capacitor-plugin-safe-area";

....

SafeArea.getSafeAreaInsets().then((data) => {
      const { insets } = data;
      document.body.style.setProperty("--ion-safe-area-top", `${insets.top}px`);
      document.body.style.setProperty(
        "--ion-safe-area-right",
        `${insets.right}px`
      );
      document.body.style.setProperty(
        "--ion-safe-area-bottom",
        `${insets.bottom}px`
      );
      document.body.style.setProperty(
        "--ion-safe-area-left",
        `${insets.left}px`
      );
    });
5 Likes

Men i fucking love you!!! THANK YOU SO MUCH!!!

In what file do you put this code?

You would want to put it in your start-up script before the app renders. For example in Vue, main.ts.

Hi thanks for the quick reply. I actually put it in App.vue, and seems to work, except for when I have a modal. Is main.ts a better place?

App.vue should be fine. It gets mounted in main.ts. Does your modal have a ion-header and ion-toolbar?

Ionic automatically adds padding to certain components. For example, the first ion-toolbar component placed in an ion-modal will receive padding according to the top edge of the device’s safe area. - (source)

This is not a final solution but is a clean workaround in Ionic-Angular:

In the app.component file

import { StatusBar } from '@capacitor/status-bar';
...


this.platform.ready().then(() => {
  StatusBar.setOverlaysWebView({
        overlay: false,
   });
   StatusBar.setBackgroundColor({
        color: '#1e2652', //color of the header
   });
});

Result for me:

1 Like

I ended up doing the following to account for the differences between Android versions <= 14 (where I set the status bar overlay to false) and Android >= 15 (where I let the status bar overlay default to true). This was necessary in my case because setting overlay to true in older versions was fixing the system nav bar but breaking my header layout due to the top status bar’s position. There are other ways to address that problem, but this was my quick solution.

app.component.ts

import { StatusBar } from '@capacitor/status-bar';
import { Device } from '@capacitor/device';

//...

async androidOverlayFixes() {
  const info = await Device.getInfo();
  const osVersion = info.osVersion;
  const insetDefault = parseInt( osVersion ) >= 15 ? 20 : 0;
  if ( parseInt( osVersion ) <= 14 ) {
    StatusBar.setOverlaysWebView( { overlay: false } );
  }
  this.computeSafeAreaInsets( insetDefault );
}

computeSafeAreaInsets( insetDefault = 0 ) {
  const windowHeight = window.innerHeight;
  const documentHeight = document.documentElement.clientHeight;
  const bottomInset = windowHeight - documentHeight;
  document.documentElement.style.setProperty(
    '--my-android-inset',
    `${Math.max(bottomInset, insetDefault)}px`
  );
};

// ...

global.css

.plt-android ion-tab-bar {
  padding-bottom: var(--my-android-inset, 0);
}

1 Like