[Feature]: natively support and document safe area insets
Description
Now that all chromium bugs (including IME related ones) seem to be resolved around the safe area insets, we should have native support and documentation
Platforms
- [ ] iOS
- [ ] Android
- [ ] Web
Request or proposed solution
As per this update all safe area inset issues (including the ones related to the IME) should be resolved in the next version of chromium. We should have native support for this in Capacitor. I think it makes sense to include this in the core capacitor code without the developer needing to install a plugin or even passing any config values.
Possible solution: we should check for the chromium versions and then do the following logic:
- If webview lower than the one that has all issues fixed (probably 140) do something like what
adjustMarginsForEdgeToEdgealready does - Otherwise, do nothing, and let the user handle the safe area insets
- Even better would be to check for the
viewport-fit=covervalue and only then do nothing. This makes the behavior consistent across web, iOS and Android
- Even better would be to check for the
Alternatives
No response
Additional Information
With this change the community can sunset all safe area/edge to edge related plugins. It would also close a lot of open issues.
We could also make this issue the overarching issues of all related ones, and close those already. A few related ones I found include:
https://github.com/ionic-team/capacitor/issues/8095 https://github.com/ionic-team/capacitor/issues/8055 https://github.com/ionic-team/capacitor/issues/8103 https://github.com/ionic-team/capacitor/issues/8093 https://github.com/ionic-team/capacitor/issues/7951
Additionally, it would be great to add some (source of truth) documentation about the safe area insets, as this chromium bug has probably caused quite some confusion among developers
I've been struggling with correct SafeArea on Android for around a year now. I was happy to see "edge-to-edge" work properly after a recent update. This then caused #8095.
I would love to see progress in the direction of this issue 👍🏽
Yeah, we are actively working on a solution for this. Expect to see some PRs related to this soon!
I'm thinking like, shouldn't all of that work out of the box after Chromium team fixes that issue (which is btw a critical issue, and regression, and I don't know why they don't patch it on Stable version...).
The Capacitor should just pass the current insets (including keyboard height as the fifth inset if the keyboard is docked to bottom) obtained with WindowInsets windowInsets = activity.getWindow().getDecorView().getRootWindowInsets(); (for Android) as browser env variables: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_environment_variables/Using_environment_variables#browser-defined_environment_variables
The challenge is perhaps only to handle the keyboard opening and closing animation.
I thought Capacitor already does this?
@croraf The passing of the safe insets should work out of the box indeed. But edge to edge mode still needs to be enabled properly on different Android versions. Moreover, for older webview versions (< 140) the chromium bug(s) still exists. So we need to account for those versions (similar to what adjustMarginsForEdgeToEdge currently already does would be fine I guess)
Hi, thanks for working on improving safe area handling in Capacitor.
I’ve been experiencing some safe area issues on iOS (content overlapping with the notch or bottom system bar). From what I understood, this proposal mostly focuses on Android / Chromium versions.
Do you know if there is already a recommended solution or upcoming change for iOS safe areas? Should we rely only on viewport-fit=cover + CSS env(safe-area-inset-*), or is there something planned in Capacitor itself to handle this more consistently?
Any guidance would be greatly appreciated
This proposal indeed focuses on Android only. Safe area insets on iOS should work as expected by using the env variables just how you would for a regular website. If you're experiencing problems, you should create a new bug report and provide a minimal reproduction
@tafelnl The Chromium fix is now deployed on Beta version of Android System Webview (which can be enabled by enrolling into Beta program here https://play.google.com/store/apps/details?id=com.google.android.webview&hl=en)
The safe-area-inset-top and safe-area-inset-bottom are injected properly now into web application.
But when the keyboard is opened I cannot fix the following behavior: https://github.com/user-attachments/assets/8ddb5199-23a9-4c51-9e05-0051fbf368fb
Do you folks encounter this problem?
- For parent HTML elements
htmlandbodythat have no height, and I triedoverfloweither hidden or not set. - For the immediate child of the
body, the"root"div element, I triedposition: absoluteandposition: fixed
Seems like there's still a bug in their implementation as someone from Google mentioned here. Not sure if that's the same bug as you're experiencing though. You should create a minimal reproduction (probably preferably without Capacitor) and submit it there to the Google team as a comment. As this is an issue with their webview
The community safe-area plugin by @tafelnl is now deprecated. https://github.com/capacitor-community/safe-area
Is there any update on when we can expect this to land natively in Capacitor?
Work seems to be done in this branch https://github.com/ionic-team/capacitor/compare/main...RDMR-902. Although I'm not sure why they seem to go the CSS env variables injection route. It shouldn't be necessary anymore because of the bugfix by the Chromium team. Maybe the Capacitor team can shed some light on this matter
@tafelnl The reason for env var injection is even though it's fixed in Chromium, there's no guarantee that users will have the updated browser engine installed. A common pattern I've seen working for many different companies who do their own analytics is that Android users are more likely to not have automatic updates turned on, and there's also the issue of some devices having their own forks of Chromium instead of depending on the Google Play version.
@jlandrum I'm aware of that. That's exactly the reason I proposed this solution:
- If webview lower than the one that has all issues fixed (probably 140) do something like what adjustMarginsForEdgeToEdge already does
- Otherwise, do nothing, and let the user handle the safe area insets
- Even better would be to check for the viewport-fit=cover value and only then do nothing. This makes the behavior consistent across web, iOS and Android
A common pattern I've seen working for many different companies who do their own analytics is that Android users are more likely to not have automatic updates turned on
This is contrary to what I'm used to. Most users of the apps I've worked with do have auto updates enabled. Or at the very least have a recent version of chromium installed
As much as I'd like to trust that would solve the problems, adjustMarginsForEdgeToEdge has created different problems for the project I'm on now. We have something that works for now, but it's not ideal. And the apps I work on tend to be ones that need to be accessible to people using the latest and greatest Android devices as well as the $20 no contract devices from Walmart so that's probably a big contributor to why we see so many out of date devices. I can't recall the exact percentage but it was close to if not above 10% which seems excessively high, but it does mean we have to do a lot of extra work to support pretty old versions of Android.
Could you elaborate on what exactly the problems are that you're experiencing with adjustMarginsForEdgeToEdge?
Work seems to be done in this branch main...RDMR-902. Although I'm not sure why they seem to go the CSS env variables injection route. It shouldn't be necessary anymore because of the bugfix by the Chromium team. Maybe the Capacitor team can shed some light on this matter
We should go for backwards compatibility and not assume everyone is using the latest version of chrome.
Just to clarify, the ideal state here would be no matter which version of chrome is on the device, the safe-area inset css variables (safe-area-inset-*) should be set in the document, right?
I respectfully disagree. Chromium is an evergreen browser meaning that the latest version will be adopted by the majority of devices in a short notice. For devices using an older chromium it's not that the app doesn't work, it will just fallback in such a way that it doesn't fully utilize the edge to edge functionality. Which in my opinion is perfectly fine. Especially since that is the current behavior already for a long time.
It would be kind of strange to workaround it and introduce all kind of hacky things just to support those devices. And possibly introduce other bugs along the way. We should just stick with the native way of doing things. That is utilizing the safe area inset envs provided by the webview itself
Just to clarify, the ideal state here would be no matter which version of chrome is on the device, the safe-area inset css variables (safe-area-inset-*) should be set in the document, right?
My proposal does exactly that. But instead of injecting the variables it will use the native envs provided by the webview. Which in some cases will be (incorrectly) reported as 0px. For those devices we should fallback to behavior similar to adjustMarginsForEdgeToEdge
I am lost now, which is the current workaround? using adjustMarginsForEdgeToEdge causes the status bar to be white with white text on my side. Without it it is of the correct color but the inset bottom is wrong. Which overlaps either with app controls or any other native overlay like ads.
I'm unable to update my app to the new Google API version because of the same issue. I'm currently using Capacitor 6 and have extended my Google API deadline until November 1. After that date, I won't be able to publish any new updates due to the ongoing problem.
@distante @thesaurabhrajput see my post over on the Ionic Forums From what I've seen, there is not a perfect solution yet until Capacitor supports safe areas natively as mentioned in this issue.
@wsamoht thanks Android Edge-to-Edge Support Plugin for Capacitor - Capawesome is working for me, but i'm not able to make the area transparent is there any solution for this?
@wsamoht thanks Android Edge-to-Edge Support Plugin for Capacitor - Capawesome is working for me, but i'm not able to make the area transparent is there any solution for this?
That plugin doesn't support transparent. See https://github.com/capawesome-team/capacitor-plugins/pull/601#issuecomment-3295462911. The plugin name isn't really accurate as it doesn't support Edge-to-Edge but actually turns it off making it like it was prior to SDK 35.
The only solution I found, as I mentioned in the forum post, was the Safe Area plugin (it has been deprecated in lieu of the creation of this issue).
For anyone wanting to support edge-to-edge now (in order to comply with Google Play requirements for example) I've unsunsetted the safe-area plugin and drastically changed the way it works. It follows the steps I outlined in the OP. I'm pretty happy with how it turned out to be. Curious to what you guys think about it. Check it out https://github.com/capacitor-community/safe-area (you should install the beta version)
Capacitor 8 is getting new Edge to Edge support which may help these issues. We should check in the beta which should include that functionality