@capacitor-community/safe-area
v7.0.0-beta.6
Published
Capacitor Plugin that patches the safe area for older versions of Chromium
Maintainers
Readme
Introduction
On web and iOS the safe area insets work perfectly fine out of the box1. That is, on these platforms the env(safe-area-inset-*) CSS variables will have the correct values by default. On Android (in combination with Capacitor), however, those CSS variables will not always have the correct values when Edge-to-Edge mode is enabled. So we need to work some magic in order to have correct behavior. This plugin does that by detecting the Chromium version a user has installed. If a user has a Chromium version lower than 140, this plugin makes sure the webview gets the safe area as a padding. The env(safe-area-inset-*) values will be set to 0px. That means for the Chromium webview versions with a bug, the developer doesn't have to worry about safe area insets at all. For all other versions, the developer should handle the safe area insets just as he would on web or iOS (by using the env(safe-area-inset-*) CSS variables). In short you can think of this plugin as a polyfill for older webview versions.
[!NOTE]
1 As with all web applications, you still need to tell the browser to use the whole available space on the screen by adding a new viewport meta value:
<meta name="viewport" content="viewport-fit=cover" />More info on the Mozilla website
Installation
npm install @capacitor-community/safe-area@beta
npx cap syncUsage
The plugin itself is enabled automatically. Additionally, you should enable native edge-to-edge mode in your MainActivity like so:
Java:
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this); // enable edge-to-edge mode
}
}Kotlin:
class MainActivity : BridgeActivity() {
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge() // enable edge-to-edge mode
}
}Additionally this plugin provides helper methods to style the system bars and its content. You can find the API docs here.
Quirks
Currently there are a few known quirks:
@capacitor/keyboard
The keyboard plugin by Capacitor has a configuration prop called resizeOnFullScreen. You should prevent to utilize that in your code by either omitting it or setting it to false. Otherwise it would interfere with the logic in this plugin. The bug that the Capacitor team is trying to workaround with that prop is already accounted for in this plugin. So you should be good to go a don't worry about it at all.
@capacitor/status-bar
When using @capacitor-community/safe-area, you should uninstall @capacitor/status-bar. Instead you can use the System Bars API this plugin provides.
adjustMarginsForEdgeToEdge setting
Capacitor provides a setting called adjustMarginsForEdgeToEdge which does a similar thing this plugin does when it detects a broken webview. It's advised to set this value to disable to prevent interference. On a similar note, you should probably remove windowOptOutEdgeToEdgeEnforcement if you've set that in the past.
Other safe area plugins
If you've installed any other safe area plugin, you should remove them to prevent interference.
These can include @capawesome/capacitor-android-edge-to-edge-support, capacitor-plugin-safe-area, @aashu-dubey/capacitor-statusbar-safe-area or even older versions of this plugin. You should make sure to uninstall those.
Respecting the viewport-fit=cover tag
When this plugin is installed, edge-to-edge mode is always enabled. Regardless of any other setting (except for broken webview versions of course). This means that the viewport-fit=cover tag is also not respected. So you should make sure any content loaded into the webview handles the env(safe-area-inset-*) accordingly. This is a known shortcoming of this plugin currently. I know how to fix this, but I'm awaiting answers from the Chromium team. Progress can be tracked here. For most use cases this shouldn't be a problem though. As most apps either do or don't support edge-to-edge.
Differences between this plugin, system-bars and status-bar
The main differences are as follows:
| | @capacitor-community/safe-area | CapacitorSystemBars5 | @capacitor/status-bar |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------- |
| Supported Capacitor versions | ✅ v7+ | ⚠️ v8+ | ✅ v7+ |
| Helper methods for styling and hiding the system bars | ✅ | ✅ | ✅ |
| Updates styling of system bars upon config changes | ✅ | ❌ | ✅ |
| Enables Edge to Edge functionality | ✅ | ✅ | ❌ |
| Fallback for broken webviews2 | ✅ Padding (does not require extra work) | ⚠️ Custom CSS vars (requires extra work and is more prone to future bugs) | ❌ |
| Workaround for keyboard bug3 | ✅ Working out of the box | ⚠️ Requires installing @capacitor/keyboard and setting resizeOnFullScreen. Their workaround also still has bugs | ❌ |
| Workaround for another keyboard bug4 | ✅ Working out of the box | ❌ | ❌ |
2 Chromium versions < 140 do not correctly report safe area insets. So we need a workaround for those webviews. This can be done using padding or custom CSS vars. This plugin advocates for using padding. As it seems to be the least breaking behavior.
3 The webview has a known bug to not resize the webview when the keyboard is shown.
4 The webview has another known bug to not properly report bottom insets when the keyboard is shown. Which will be fixed in Chromium 144
5 The Capacitor team themselves are also working on a similar
solution by means of a CapacitorSystemBars plugin. It's still a
work in progress though. Currently that PR is merged as is and in a beta state. Their design/approach philosophy also
deviates from the one in this plugin.
System Bars API
This plugin provides a few helper methods for styling the system bars. It's designed to be a partial drop-in replacement for the @capacitor/status-bar plugin. It doesn't support a few things, like setOverlaysWebView for example, as those aren't applicable when handling the safe areas using insets.
[!NOTE] On iOS this API requires "View controller-based status bar appearance" (
UIViewControllerBasedStatusBarAppearance) set toYESinInfo.plist. Read about Configuring iOS for help.The status bar visibility defaults to visible and the style defaults to
UIStatusBarStyle.default. You can change these defaults by addingUIStatusBarHiddenand/orUIStatusBarStyleinInfo.plist.
setSystemBarsStyle(...)
setSystemBarsStyle(options: SystemBarsStyleOptions) => Promise<void>| Param | Type |
| ------------- | ------------------------------------------------------------------------- |
| options | SystemBarsStyleOptions |
showSystemBars(...)
showSystemBars(options: SystemBarsVisibilityOptions) => Promise<void>| Param | Type |
| ------------- | ----------------------------------------------------------------------------------- |
| options | SystemBarsVisibilityOptions |
hideSystemBars(...)
hideSystemBars(options: SystemBarsVisibilityOptions) => Promise<void>| Param | Type |
| ------------- | ----------------------------------------------------------------------------------- |
| options | SystemBarsVisibilityOptions |
Interfaces
SystemBarsStyleOptions
| Prop | Type | Description | Default |
| ----------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
| style | SystemBarsStyle | Style of the content of the system bars. | 'DEFAULT' |
| type | SystemBarsType | The system bar to which to apply the style. Providing null means it will be applied to both system bars. On iOS the home indicator cannot be styled. It will always automatically be applied a color by iOS out of the box. | null |
SystemBarsVisibilityOptions
| Prop | Type | Description | Default |
| ---------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------- | ----------------- |
| type | SystemBarsType | The system bar to hide or show. Providing null means it will toggle both system bars. | null |
Enums
SystemBarsStyle
| Members | Value | Description |
| ------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Dark | 'DARK' | Light system bar content on a dark background. |
| Light | 'LIGHT' | For dark system bar content on a light background. |
| Default | 'DEFAULT' | The style is based on the device appearance or the underlying content. If the device is using dark mode, the system bars content will be light. If the device is using light mode, the system bars content will be dark. |
SystemBarsType
| Members | Value | Description |
| ------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| StatusBar | 'STATUS_BAR' | The top status bar on both Android and iOS. |
| NavigationBar | 'NAVIGATION_BAR' | The navigation bar on both Android and iOS. On iOS this is the "home indicator". On Android this is either the "navigation bar" or the "gesture bar". |
Config
| Prop | Type | Description | Default |
| ------------------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
| statusBarStyle | SystemBarsStyle | Indicates which style to apply to the status bar initially. | null |
| navigationBarStyle | SystemBarsStyle | Indicates which style to apply to the navigation bar initially. On iOS the home indicator cannot be styled. It will always automatically be applied a color by iOS out of the box. | null |
| offsetForKeyboardInsetBug | boolean | | |
Examples
In capacitor.config.json:
{
"plugins": {
"SafeArea": {
"statusBarStyle": undefined,
"navigationBarStyle": undefined,
"offsetForKeyboardInsetBug": undefined
}
}
}In capacitor.config.ts:
/// <reference types="@capacitor-community/safe-area" />
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
plugins: {
SafeArea: {
statusBarStyle: undefined,
navigationBarStyle: undefined,
offsetForKeyboardInsetBug: undefined,
},
},
};
export default config;