npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@capacitor-community/safe-area

v7.0.0-beta.8

Published

Capacitor Plugin that patches the safe area for older versions of Chromium

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 achieve the desired 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 (regular) web applications, you still need to tell the browser to scale the viewport as so to fill the device display by setting a viewport meta value like so:

<meta name="viewport" content="viewport-fit=cover" />

More info on the Mozilla website about setting the <meta name="viewport"> and using CSS env().

Installation

npm install @capacitor-community/safe-area@beta
npx cap sync

Usage

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.

Setup

This plugin might conflict with some of your existing setup. Please go through the following steps, to ensure proper functioning of this plugin.

If you're installing this plugin into a fresh Capacitor setup, you can probably skip most - if not all - of these steps.

@capacitor/keyboard

The keyboard plugin by Capacitor has a configuration prop called resizeOnFullScreen. You should either omit it or set it to false. Otherwise it would interfere with the logic in this plugin. The bug that the Capacitor team is trying to fix 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. It's advised to either omit this value or set it to disable to prevent interference. This plugin already does a similar thing when it detects a broken webview.

windowOptOutEdgeToEdgeEnforcement

If you've set windowOptOutEdgeToEdgeEnforcement in your AndroidManifest.xml, you should probably remove it. It has been deprecated and shouldn't be necessary when using this plugin anyways.

Extending BridgeWebViewClient and calling setWebViewClient

If you're running Capacitor v7 and have extended the BridgeWebViewClient by calling bridge.setWebViewClient in your code, you should update your code so that it extends SafeAreaWebViewClient instead. In Capacitor v8 this can and will be worked around another way, so you shouldn't have to worry about that anymore.

Other safe area plugins

If you've installed any other safe area plugin, you should remove them to prevent interference.

Examples of these are: @capawesome/capacitor-android-edge-to-edge-support, capacitor-plugin-safe-area and @aashu-dubey/capacitor-statusbar-safe-area.

Just make sure to uninstall those and you should be good to go.

Earlier versions of this plugin

Alpha versions of this plugin (@capacitor-community/safe-area@alpha) are deprecated and usage of those versions is advised against. Please migrate to a beta or latest channel instead. Differences between the older versions and the newer versions are outlined here.

Capacitor v8

As of this writing, Capacitor v8 has just been released. But if you're already using it, you should set the following in your capacitor.config.json:

{
  "plugins": {
    "SystemBars": {
      "insetsHandling": "disable"
    }
  }
}

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 | ✅ | ✅ | ❌ | | Option to opt out of handling insets for Android | ✅ | ❌ | N/A | | Philosophy2 | ✅ Native approach. Aligns with iOS and web behavior. Does not require extra work. Fallback to padding for broken webviews. | ⚠️ All or nothing approach using custom CSS vars injection. Requires extra work (migrating from envs to vars). Doesn't distinguish between broken and fixed webview versions. It's arguably more prone to future bugs. | N/A | | Fallback supported on Android versions | ✅ Android 6+ | ❌ Android 15+ (broken behavior on older versions) | N/A | | Workaround for resizing keyboard bug3 | ✅ Working out of the box | ⚠️ Requires installing @capacitor/keyboard and setting resizeOnFullScreen. Their workaround also still has bugs | ❌ | | Workaround for inset keyboard bug4 | ✅ Working out of the box | ❌ | N/A | | Detects viewport-fit=cover changes | ✅ Works for any arbitrary web content | ⚠️ Works only for web content that has Capacitor v8 set up | N/A |

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.

FAQ

Do I need this plugin?

You probably do! Apps targeting Android sdk version 36 will automatically be in edge to edge mode on a device running Android 16+. This means you should properly support safe area insets. This seemingly works just fine. However Chromium versions < 140 have a bug that causes the webview to receive incorrect values (0px). This plugin works around that by adding a padding to the webview for those devices. As a bonus, this plugin resizes the webview upon keyboard visibility changes, something that also isn't standard.

Why doesn't Capacitor take care of this out of the box?

They can and they should. They tried / are trying actually. But IMHO their approach isn't ready for production (yet). The differences between their approach and the one of this plugin are outlined here. I try to adhere to their coding style and I am actively providing feedback to the Capacitor team in hopes they will - sometime - upstream this plugin into their core codebase.

I don't care about safe area insets or edge to edge functionality!

That's not a question ;) And your users might care about them though! So it's recommended to support them. But if you really do not want to support edge to edge, you've got two options:

  1. Remove the viewport-fit=cover meta tag if you've set that. Mind you that this removes edge to edge support entirely, for all platforms (Android, iOS and web)
  2. If you want to only remove support for Android, set the following value in your capacitor.config.json:
    {
      "plugins": {
        "SafeArea": {
          "detectViewportFitCoverChanges": false,
          "initialViewportFitCover": false
        }
      }
    }
    This effectively makes this plugin to only add padding around the webview on all of your Android devices. And disables detecting the viewport-fit value and disables passing through insets (because they're already consumed by the padding).

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 to YES in Info.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 adding UIStatusBarHidden and/or UIStatusBarStyle in Info.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 | | detectViewportFitCoverChanges | boolean | This plugin detects changes to the viewport-fit=cover meta tag. This comes in handy when you do not know for sure if the content loaded into the webview will have viewport-fit set to cover. For most use cases you do not need to touch this config variable. However if you know for sure you want to always keep the initialViewportFitCover value unchanged, you could disable this feature by setting it to false. Be aware that this might result in a visually broken UI if the content loaded into the webview does not correctly handle safe area insets. This option is only supported on Android. | true | | initialViewportFitCover | boolean | Set an initial value for the to be detected viewport-fit=cover. For most apps this value will eventually be true. Therefore this value is set to true by default to help prevent layout jumps and glitches. If you know (or want) the value to be false initially, you can set it here. The value will always end up correctly, no matter what you set here, as long as detectViewportFitCoverChanges is set to true. It only exists to help prevent layout jumps and glitches. This option is only supported on Android. | true | | offsetForKeyboardInsetBug | boolean | | |

Examples

In capacitor.config.json:

{
  "plugins": {
    "SafeArea": {
      "statusBarStyle": undefined,
      "navigationBarStyle": undefined,
      "detectViewportFitCoverChanges": undefined,
      "initialViewportFitCover": 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,
      detectViewportFitCoverChanges: undefined,
      initialViewportFitCover: undefined,
      offsetForKeyboardInsetBug: undefined,
    },
  },
};

export default config;