Skip to content

Electrobun Webview Tag

<electrobun-webview> embeds a separate native BrowserView and keeps its position synchronized with an element in the host page. It behaves like an isolated iframe, but the embedded content is rendered by its own native webview rather than inside the host document.

Import electrobun/view once in the host page. That module registers the custom element and augments TypeScript’s DOM types.

<electrobun-webview
id="documentation"
src="https://example.com"
sandbox
style="display: block; width: 100%; height: 480px"
></electrobun-webview>
import type { WebviewTagElement } from "electrobun/view";
import "electrobun/view";
const webview = document.querySelector("electrobun-webview");
if (!webview) throw new Error("The embedded webview was not found");
webview.on("dom-ready", () => {
console.log("Embedded content is ready", webview.webviewId);
});
webview.loadURL("https://example.com/docs");
const typedWebview: WebviewTagElement = webview;
void typedWebview;

Attributes

AttributeValuePurpose
srcURLInitial URL. Changing it navigates the webview.
htmlHTML stringInitial inline document. Changing it loads the new HTML.
preloadJavaScript stringCode evaluated before the embedded page’s scripts.
partitionstringPersistent session/storage partition name.
renderernative or cefRenderer for this webview. Defaults to native.
sandboxboolean attributeDisables Electrobun RPC in the child while retaining events and navigation controls.
transparentboolean attributeStarts the native layer transparent.
passthroughboolean attributeStarts with pointer input passing through to the host page.
spellcheckboolean attributeEnables native WKWebView spell checking where supported.
maskscomma-separated selectorsCuts holes in the native layer for matching host elements.
navigation-rulesJSON string arrayInitial native navigation allow/block rules.

Boolean attributes are enabled by their presence. For spellcheck, an explicit value of "false" is also treated as disabled.

<electrobun-webview
src="https://example.com"
renderer="cef"
partition="account-a"
sandbox
transparent
passthrough
masks=".toolbar, .popover"
navigation-rules='["^*", "https://example.com/*"]'
></electrobun-webview>

Set creation-only attributes such as renderer, partition, and sandbox before attaching the element to the document. Use the methods below for runtime changes.

import "electrobun/view";
const webview = document.querySelector("electrobun-webview");
if (!webview) throw new Error("The embedded webview was not found");
webview.loadURL("https://example.com");
webview.loadHTML("<!doctype html><title>Inline document</title><h1>Hello</h1>");
webview.reload();
webview.goBack();
webview.goForward();
const [canGoBack, canGoForward] = await Promise.all([
webview.canGoBack(),
webview.canGoForward(),
]);
console.log({ canGoBack, canGoForward });

setNavigationRules(rules) applies rules in native code. * is a wildcard, ^ marks a blocking rule, and the last matching rule wins. With no matching rule, navigation is allowed.

import "electrobun/view";
const webview = document.querySelector("electrobun-webview");
if (!webview) throw new Error("The embedded webview was not found");
webview.setNavigationRules([
"^*",
"https://example.com/*",
"https://cdn.example.com/*",
]);

An empty rules array restores the default allow behavior.

Visibility And Input

The toggle methods accept an explicit state. Omit it to invert the current state.

import "electrobun/view";
const webview = document.querySelector("electrobun-webview");
if (!webview) throw new Error("The embedded webview was not found");
webview.toggleTransparent(true);
webview.togglePassthrough(true);
webview.toggleHidden(false);
webview.syncDimensions(true);
console.log({
transparent: webview.transparent,
passthrough: webview.passthroughEnabled,
hidden: webview.hidden,
});

syncDimensions(true) forces an immediate geometry and mask update. Normal layout changes are synchronized automatically.

Mask Selectors

The native webview is a separate layer above the host page, so ordinary z-index cannot place host DOM over it. A mask selector cuts rectangular holes in the native layer. Matching host elements then remain visible and receive input.

<div class="toolbar">Host controls</div>
<electrobun-webview
src="https://example.com"
sandbox
masks=".toolbar, .context-menu"
></electrobun-webview>
import "electrobun/view";
const webview = document.querySelector("electrobun-webview");
if (!webview) throw new Error("The embedded webview was not found");
webview.addMaskSelector(".autocomplete");
webview.removeMaskSelector(".autocomplete");
console.log([...webview.maskSelectors]);

Each selector can match any number of elements. Invalid selectors are ignored. Masks use bounding rectangles; rounded corners and partial alpha do not alter the rectangular cutout.

On Linux, passthrough and mask punch-through are unavailable for embedded views inside transparent BrowserWindows. Use a non-transparent parent for those overlays. On Windows, WebView2 does not honor these overlay operations; set bundleCEF: true and use the CEF renderer when masks or passthrough are required.

Spell Check

import "electrobun/view";
const webview = document.querySelector("electrobun-webview");
if (!webview) throw new Error("The embedded webview was not found");
const supported = await webview.setSpellCheck(true);
console.log({ supported, enabled: webview.spellCheckEnabled });

The promise resolves to true only when the current renderer supports the change. Native WKWebView on macOS is currently supported; other renderers return false without changing renderer state.

Find And Developer Tools

import "electrobun/view";
const webview = document.querySelector("electrobun-webview");
if (!webview) throw new Error("The embedded webview was not found");
webview.findInPage("Electrobun", { forward: true, matchCase: false });
webview.stopFindInPage();
webview.openDevTools();
webview.closeDevTools();
webview.toggleDevTools();
webview.executeJavascript("document.documentElement.dataset.embedded = 'true'");

Events

Use on and off for custom-element events. A listener receives a CustomEvent; payload shape depends on the native event.

import "electrobun/view";
const webview = document.querySelector("electrobun-webview");
if (!webview) throw new Error("The embedded webview was not found");
const onNavigation = (event: CustomEvent) => {
console.log("Navigation payload", event.detail);
};
webview.on("did-navigate", onNavigation);
webview.off("did-navigate", onNavigation);

Supported event names are:

  • will-navigate
  • did-navigate
  • did-navigate-in-page
  • did-commit-navigation
  • dom-ready
  • host-message
  • new-window-open
  • download-started
  • download-progress
  • download-completed
  • download-failed
  • load-started
  • load-committed
  • load-finished

Embedded content can emit a host-message from its preload script:

window.__electrobunSendToHost({ type: "ready", documentTitle: document.title });

The host receives that value in the event detail. This event bridge remains available in sandbox mode; Electrobun RPC does not.

Properties

PropertyTypeNotes
webviewIdnumber | nullNative view ID after initialization.
srcstring | nullAttribute-backed URL.
htmlstring | nullAttribute-backed inline HTML.
preloadstring | nullAttribute-backed preload source.
renderer"native" | "cef"Attribute-backed renderer.
sandboxbooleanRead-only initialized sandbox state.
transparentbooleanCurrent transparency state.
passthroughEnabledbooleanCurrent input passthrough state.
spellCheckEnabledbooleanRequested spell-check state.
hiddenbooleanCurrent native visibility state.
maskSelectorsSet<string>Active host-page mask selectors.

The element also inherits standard HTMLElement properties such as id, style, and dataset.