Skip to content

bug(status-bar): iOS WebView moves under the status bar after a full-screen modal is dismissed #2625

Open

Description

@kidzki

Bug Report

Plugin(s)

  • @capacitor/status-bar 8.0.4
  • @capacitor/browser 8.0.5 (used to present the full-screen modal)

Capacitor Version

Installed Dependencies:

  @capacitor/android: not installed
  @capacitor/cli: 8.6.0
  @capacitor/core: 8.6.0
  @capacitor/ios: 8.6.0

[success] iOS looking great! 👌

Platform(s)

iOS

Current Behavior

With overlaysWebView: false, the WebView starts below the status bar after launch. After a full-screen modal is dismissed, the WebView fills the whole window again:

  • The page content sits under the status bar.
  • The status bar background view (backgroundColor) is no longer visible.
  • StatusBar.getInfo() still returns overlays: false.

The layout stays wrong until the next rotation. Rotating to landscape and back restores it.

The full-screen modal in the reproduction is Browser.open() with the default presentation style. With presentationStyle: 'popover' the layout stays correct.

Expected Behavior

After a full-screen modal is dismissed, the WebView is below the status bar again, and the status bar background view is visible, as before the modal was presented.

Code Reproduction

https://github.com/kidzki/capacitor-status-bar-repro

  1. npm install && npm run build && npx cap sync ios
  2. Run the app on an iPhone simulator. The yellow box shows RESULT: OK.
  3. Tap Open in-app browser (full screen), then close the browser.
  4. The yellow box shows RESULT: BUG: window.innerHeight equals screen.height, and the sticky header sits under the status bar.

Configuration:

"StatusBar": {
  "overlaysWebView": false,
  "backgroundColor": "#ffffff",
  "style": "LIGHT"
}

Other Technical Details

  • Observed on the iPhone 18 Pro simulator, iOS 27.2, Xcode 27.2.
  • Also observed in our app on a physical iPhone 17 Pro with iOS 26.6.4, 27.0.1 and 27.2. Our app opens Browser.open() full screen for the login.
  • The page does not use viewport-fit=cover.
  • The app shell is the unchanged ios template from npx cap add ios (Capacitor 8.6.0).

Additional Context

CAPBridgeViewController.loadView() sets view = webView, so the WebView is the root view. When a full-screen modal is dismissed, UIKit sets the root view back to the full window bounds.

The plugin positions the WebView in resizeWebView(). It calls that function after setOverlaysWebView and after a rotation (capacitorViewWillTransition). On capacitorViewDidAppear, which also fires after the modal is dismissed, handleViewDidAppear calls setOverlaysWebView(config.overlaysWebView). That function returns early because the value did not change (if overlay == isOverlayingWebview { return }), so the plugin does not lay out the WebView again.

Possible fixes:

  1. Lay out again in handleViewDidAppear. We tried this: it restores the layout, but the jump is visible because viewDidAppear fires after the dismiss animation.
  2. Observe the WebView layer (position, bounds) while overlaysWebView is false, and move the WebView back below the status bar when its origin changes. We tried this: the layout is restored without a visible jump. A pull request with this change follows.
  3. Capacitor core sends a notification from viewWillLayoutSubviews or viewWillAppear, and the plugin lays out there. Not tried.
  4. @capacitor/browser presents with .overFullScreen instead of .fullScreen, so UIKit keeps the presenting view in place. Not tried. This fixes only the browser, not other full-screen modals.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions