Skip to content

[iOS][New Architecture] WKWebView becomes fully transparent because backgroundColor is never forwarded to RNCWebViewImpl under Fabric #3994

Description

@Paperkeem

Bug description

On the New Architecture (Fabric), the iOS WKWebView is created fully transparent (opaque = NO, no background color). Any region of the web content that has transparent CSS shows whatever is behind the RN surface — typically the black UIWindow — and the same black/blank areas appear in the snapshot layers during allowsBackForwardNavigationGestures swipe transitions.

The same app and the same web content render correctly (opaque white webview) on the old architecture (Paper). This is a regression introduced by the architecture switch, not by the web content.

Environment

react-native-webview 14.0.1
react-native 0.86.2 (New Architecture / Fabric — mandatory since RN 0.82)
Platform iOS (reproduced on iPhone 14 real device and iOS simulator)
Old architecture (RN 0.77.3 + webview 13.16.0, same app/web content) not reproducible — webview is opaque white as expected

To Reproduce

  1. Create a New Architecture RN app (RN 0.82+).

  2. Render a plain <WebView source={{ uri }} /> (no style prop) pointing to any page that contains transparent regions, e.g.:

    <body style="background: transparent">
      <div style="height: 50vh; background: white">opaque part</div>
      <!-- rest of the body is transparent -->
    </body>
  3. Run on iOS.

Screenshots/Videos

Image

banner/icon chips (web-painted) render fine; the page background the web leaves transparent shows the black window through

Expected behavior

Expected: transparent CSS regions render on an opaque white webview background — this is both the Paper behavior and what the library's own JS default style
requests (webView: { backgroundColor: '#ffffff' }, see "Root cause analysis" below).

Actual: transparent regions show the black window behind the RN surface. Also visible as black/blank sheets during back/forward swipe-gesture transitions.

Root cause analysis

RNCWebViewImpl derives the webview's opacity from the last color passed to setBackgroundColor: and applies it when the WKWebView is created:

// RNCWebViewImpl.m — didMoveToWindow
_webView = [[RNCWKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig];
[self setBackgroundColor: _savedBackgroundColor];

// RNCWebViewImpl.m — setBackgroundColor:
CGFloat alpha = CGColorGetAlpha(backgroundColor.CGColor);
BOOL opaque = (alpha == 1.0);
self.opaque = _webView.opaque = opaque;
_webView.scrollView.backgroundColor = backgroundColor;
_webView.backgroundColor = backgroundColor;
  • On Paper, the view-manager prop dispatch calls setBackgroundColor: automatically, delivering the library's own JS default style (src/WebView.styles.tswebView: { backgroundColor: '#ffffff' }). Result: _savedBackgroundColor = white, opaque = YES.
  • On Fabric, the component wrapper (apple/RNCWebView.mm) never reads ViewProps.backgroundColor and never forwards it to RNCWebViewImpl — the base RCTViewComponentView consumes the prop by painting its own layer instead. _savedBackgroundColor therefore stays nil, CGColorGetAlpha(nil.CGColor) evaluates to 0, and the webview is configured transparent.

In other words, the implementation has always depended on the framework forwarding backgroundColor into the impl, and that (implicit, reflection-based) delivery no longer exists under Fabric.

Proposed fix

Forward the standard backgroundColor view prop to the impl in RNCWebView.mm's updateProps:oldProps:, e.g.:

const auto &oldViewProps = *std::static_pointer_cast<const RNCWebViewProps>(_props);
const auto &newViewProps = *std::static_pointer_cast<const RNCWebViewProps>(props);

if (oldViewProps.backgroundColor != newViewProps.backgroundColor) {
  [_view setBackgroundColor:RCTUIColorFromSharedColor(newViewProps.backgroundColor)];
}

Since the JS layer already ships backgroundColor: '#ffffff' in the default style, wiring the relay restores Paper parity without further changes, and also makes intentional transparent webviews (style={{ backgroundColor: 'transparent' }}) work as documented.

Happy to open a PR for this if the direction is agreed.

Activity

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions