A Safari-style browser window web component for demos and tutorials. Features source code viewing, full-screen expand mode, CodePen export, automatic theme detection, and full theming support.
View Documentation | Live Demos | API Reference
Based on @zachleat/browser-window with significant enhancements.
npm install @profpowell/browser-windowimport '@profpowell/browser-window';<!-- unpkg -->
<script type="module" src="https://unpkg.com/@profpowell/browser-window"></script>
<!-- jsdelivr -->
<script type="module" src="https://cdn.jsdelivr.net/npm/@profpowell/browser-window"></script><script type="module" src="path/to/browser-window.js"></script><browser-window url="https://example.com" title="My Demo">
<img src="screenshot.png" alt="Demo screenshot">
</browser-window><browser-window
src="demos/my-demo.html"
url="https://example.com"
title="CSS Demo">
</browser-window>The component automatically respects your system's prefers-color-scheme preference. You can also explicitly set the mode:
<!-- Follows system preference (default) -->
<browser-window src="demo.html"></browser-window>
<!-- Always light -->
<browser-window mode="light" src="demo.html"></browser-window>
<!-- Always dark -->
<browser-window mode="dark" src="demo.html" shadow></browser-window>The component is resizable by default. Drag the bottom-right corner to resize:
<!-- Set initial size with CSS -->
<browser-window src="demo.html" style="height: 400px; width: 600px;">
</browser-window>| Attribute | Type | Default | Description |
|---|---|---|---|
url |
string | '' |
URL to display in the address bar |
title |
string | hostname from url | Title shown in the URL bar |
src |
string | '' |
Path to HTML file to load in iframe (enables source viewing) |
mode |
'light' | 'dark' |
auto | Color scheme. Omit to follow system preference |
shadow |
boolean | false |
Add drop shadow to the window |
device |
string | '' |
Device preset for phone/tablet bezel mode |
device-color |
string | 'midnight' |
Bezel color: midnight, silver, gold, blue, white |
orientation |
'portrait' | 'landscape' |
'portrait' |
Device orientation |
show-safe-areas |
boolean | false |
Show safe area overlay bands (device mode) |
| Preset | Device | Screen |
|---|---|---|
iphone-16 |
iPhone 16 | 393 x 852 |
iphone-16-pro-max |
iPhone 16 Pro Max | 440 x 956 |
iphone-se |
iPhone SE | 375 x 667 |
pixel-9 |
Pixel 9 | 412 x 923 |
pixel-9-pro-xl |
Pixel 9 Pro XL | 448 x 998 |
galaxy-s24 |
Galaxy S24 | 360 x 780 |
ipad-air |
iPad Air | 820 x 1180 |
ipad-pro-13 |
iPad Pro 13" | 1032 x 1376 |
ipad-mini |
iPad mini | 744 x 1133 |
Render content inside a realistic phone or tablet bezel:
<!-- iPhone 16 -->
<browser-window device="iphone-16" src="app.html"></browser-window>
<!-- Landscape Pixel 9 with silver bezel -->
<browser-window device="pixel-9" orientation="landscape" device-color="silver" src="app.html">
</browser-window>
<!-- iPad Air with safe area overlays -->
<browser-window device="ipad-air" show-safe-areas src="app.html"></browser-window>When src is set, a code icon appears in the URL bar. Click to toggle between the rendered content and the source code.
- Double-click the title bar to maximize/restore
- Click the green button to maximize
- Press Escape or click the overlay to restore
- Maximized windows display as a centered modal with backdrop
When src is set, a share button provides:
- Share... - Native Web Share API (on supported devices)
- Open in CodePen - Export demo to CodePen with HTML/CSS/JS separated
Direct download link for the source HTML file.
The component automatically follows your operating system's light/dark mode preference using prefers-color-scheme. Set the mode attribute to override this behavior.
Drag the bottom-right corner to resize the component. The content area (iframe or source view) automatically adjusts to fill the available space. Resizing is disabled when maximized.
- Touch-friendly control buttons with proper hit targets (44px minimum)
- Responsive layout that adapts to narrow screens
- URL bar text truncates gracefully on small screens
All visual aspects can be customized via CSS custom properties:
browser-window {
--browser-window-bg: #ffffff;
--browser-window-header-bg: #f6f8fa;
--browser-window-border-color: #d1d5da;
--browser-window-border-radius: 8px; /* or var(--radius-m) for Vanilla Breeze */
--browser-window-inner-radius: 6px; /* URL bar, buttons */
--browser-window-border-width: 1px;
--browser-window-border-style: solid;
--browser-window-text-color: #24292e;
--browser-window-text-muted: #586069;
--browser-window-url-bg: #ffffff;
--browser-window-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
--browser-window-close-color: #ff5f57;
--browser-window-minimize-color: #febc2e;
--browser-window-maximize-color: #28c840;
--browser-window-accent-color: #2563eb;
--browser-window-hover-bg: #f3f4f6;
--browser-window-content-bg: #ffffff;
--browser-window-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--browser-window-mono-font: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
/* Device mode */
--browser-window-bezel-color: #1a1a1a;
--browser-window-status-bar-color: rgba(255,255,255,0.9);
--browser-window-home-indicator-color: rgba(255,255,255,0.3);
--browser-window-safe-area-color: oklch(0.65 0.2 250 / 0.25);
/* Layout */
--browser-window-margin: 1rem 0;
/* Z-index (for stacking context control) */
--browser-window-z-index: 9999;
--browser-window-overlay-z-index: 9998;
--browser-window-menu-z-index: 1000;
}/* Purple theme */
browser-window.purple-theme {
--browser-window-accent-color: #8b5cf6;
--browser-window-header-bg: #faf5ff;
--browser-window-border-color: #c4b5fd;
}- Full keyboard navigation with visible focus indicators
- ARIA labels on all interactive elements
role="dialog"andaria-modalwhen maximized- Respects
prefers-reduced-motionfor animations - Escape key closes maximized view and menus
- Touch targets meet WCAG 2.1 minimum size requirements
Works in all modern browsers that support Web Components:
- Chrome/Edge 67+
- Firefox 63+
- Safari 13.1+
Note: device scaling relies on ResizeObserver, and source fetching uses AbortController.
# Install dependencies
npm install
# Start development server
npm run dev
# Run linter
npm run lint
# Run tests
npm test
# Build for production
npm run build
# Generate custom elements manifest
npm run analyze| Script | Description |
|---|---|
npm run dev |
Start the local Vite dev server (default: port 5173) |
npm run build |
Build for production (JS + types) |
npm run lint |
Run ESLint |
npm run lint:fix |
Run ESLint with auto-fix |
npm run format |
Format code with Prettier |
npm run test |
Run test suite |
npm run test:ui |
Run tests with interactive UI |
npm run analyze |
Generate custom-elements.json manifest |
- <code-block> - Syntax-highlighted code block web component with copy button
- @zachleat/browser-window - The original component this project is based on
MIT