Window Management

PWAs get their own window -- and with it, the old 90s window APIs that tabbed browsers killed. The Multi-Screen Window Placement API and Windows Controls Overlay go further, letting PWAs span displays and render HTML in the title bar.

June 12, 20264 min read2 / 6

window.moveTo() and window.resizeTo() shipped in Netscape 2.0 in 1996. They let JavaScript reposition and resize the browser window.

They have been effectively dead for 25 years.

Once tabbed browsing arrived, a JavaScript call that tried to move "the window" became ambiguous -- there were other tabs in that window, and other apps using it. Browsers silently ignored the calls. The APIs stayed in the spec but did nothing.

Install your app as a PWA and you get your own window. A window no other tab shares. And suddenly the APIs from 1996 work again.

Your Own Window

An installed PWA runs in a standalone window. That window belongs to the app. No other tabs, no other origins. When you call window.moveTo(100, 200), the browser moves that window.

You can also open additional windows of the same app:

JavaScript
const newWindow = window.open('/dashboard', '_blank', 'width=800,height=600')

Each opened window is a new instance of your PWA, at the specified dimensions, positioned wherever you like. All windows share the same origin and can communicate via BroadcastChannel or postMessage.

This is what made multi-window creative tools possible on the web -- a canvas editor where the tool palette is a separate window, positioned where the user last left it.

Multi-Screen Window Placement

Single-screen positioning is useful. Multi-screen positioning is the real unlock. Professionals commonly have two, three, or more monitors -- a presentation app that can move its slide view to the external projector is solving a real problem.

JavaScript
// Request permission and get screen details const screens = await window.getScreenDetails() // All connected screens screens.screens.forEach(screen => { console.log(screen.label) // "Built-in Retina Display", "DELL U2722D", etc. console.log(screen.availLeft) // x-coordinate of the screen console.log(screen.availTop) // y-coordinate of the screen console.log(screen.availWidth) // usable width (excludes OS taskbar) console.log(screen.availHeight) // usable height console.log(screen.isPrimary) // true for the main display console.log(screen.isExtended) // true for any secondary display }) // The screen the current window is on console.log(screens.currentScreen)

window.getScreenDetails() requires a user permission grant the first time it is called. After permission is granted, screenschange fires whenever the connected display configuration changes.

To move the current window to a specific screen:

JavaScript
const [primaryScreen, secondaryScreen] = screens.screens.sort( (a, b) => a.isPrimary ? -1 : 1 ) // Move to secondary screen, fill it window.moveTo(secondaryScreen.availLeft, secondaryScreen.availTop) window.resizeTo(secondaryScreen.availWidth, secondaryScreen.availHeight)

This API is not limited to installed PWAs -- it works on websites running in a browser tab too. The permission dialog is the same.

Window Management APIs: legacy moveTo/resizeTo, multi-screen placement, and Windows Controls Overlay ExpandWindow Management APIs: legacy moveTo/resizeTo, multi-screen placement, and Windows Controls Overlay

Windows Controls Overlay

The title bar is wasted space by default. A thin strip showing the app name and three window control buttons. Nothing else.

Windows Controls Overlay changes that. When you opt in via the manifest, the browser lets your HTML and CSS render all the way into the title bar region -- behind the traffic-light buttons on macOS, and to the left of the close/minimize/maximize buttons on Windows.

JSON
{ "display_override": ["window-controls-overlay"], "display": "standalone" }

With that in the manifest, the PWA gains CSS environment variables that tell you the exact geometry of the non-draggable region:

CSS
.title-bar-content { position: fixed; left: env(titlebar-area-x); top: env(titlebar-area-y); width: env(titlebar-area-width); height: env(titlebar-area-height); /* -webkit-app-region: drag; makes this area draggable */ }

A search bar in the title bar. A tab strip. The current document name. These are all possible with CSS and env() variables.

The classic example is Wikipedia as a PWA: a search field sits directly in the title bar. The user can type a search without the app viewport scrolling at all.

Current support: Chrome and Edge on desktop. Not Safari, not mobile.

Support

window.getScreenDetails() and Windows Controls Overlay both require Chromium on desktop. window.moveTo() and window.resizeTo() work in any browser when the app is running in a standalone window.

JavaScript
if ('getScreenDetails' in window) { // Multi-Screen Window Placement API is available }

The next OS integration API makes your PWA act like a default file opener. File Handling and Protocol Handlers let a double-click on a .recipe file in the OS file manager launch your PWA with that file ready to read.

The Essentials

  1. An installed PWA runs in its own window -- moveTo, resizeTo, and open() work again because no other tabs share the window.
  2. window.getScreenDetails() returns all connected screens with coordinates, sizes, and labels. Works in browser tabs too (not PWA-only).
  3. screenschange fires when the display configuration changes -- screens added, removed, or repositioned.
  4. Windows Controls Overlay ("display_override": ["window-controls-overlay"]) lets you render HTML/CSS in the title bar. Use env(titlebar-area-x/y/width/height) for geometry. Chrome/Edge desktop only.
  5. All window control APIs require Chromium. The multi-screen API also works in regular browser tabs.

Further Reading and Watching