Customizing PWA Title Bars with Window Controls Overlay
The Window Controls Overlay feature in Chromium-based browsers allows Progressive Web Apps (PWAs) to feel more like native desktop applications by reclaiming the full width of the window's title bar. This article provides a complete overview of how this feature works, covering how it extends the web viewport to the top of the app window, how developers use the Web App Manifest to enable it, and how CSS environment variables and JavaScript APIs are used to seamlessly place custom content next to the operating system's native window controls.
Extending the Viewport
By default, an installed desktop PWA displays a dedicated system title bar at the top of the window, which houses the app title and the minimize, maximize, and close buttons. The Window Controls Overlay feature removes this full-width bar. Instead, it extends the web content area—the viewport—all the way to the very top edge of the application window. The browser then renders only the essential native window control buttons as a floating overlay on top of the web content, freeing up the rest of the horizontal space for custom HTML elements like search bars, navigation tabs, or custom menus.
Enabling the Feature in the Manifest
To activate this behavior, developers must explicitly request it in
the PWA's manifest.json file. This is done using the
display_override property. By setting
"display_override": ["window-controls-overlay"], the app
instructs the Chromium browser to prioritize the overlay layout over the
standard standalone or minimal-ui display
modes when running on a supported desktop operating system.
Positioning Content with CSS Environment Variables
Because the native window controls (close, minimize, maximize) still exist as an overlay, developers need a way to prevent their custom content from being hidden underneath those buttons. Furthermore, these controls appear on the right side of the window on Windows and Linux, and on the left side on macOS.
Chromium solves this by providing four CSS environment variables that define the exact safe area available in the title bar region:
env(titlebar-area-x): The distance from the left edge of the viewport to where the safe title bar area begins.env(titlebar-area-y): The distance from the top edge of the viewport (usually 0px).env(titlebar-area-width): The total width of the safe area, excluding the native window controls.env(titlebar-area-height): The height of the native title bar area.
By applying these variables to a fixed-position header container in CSS, the custom title bar automatically adapts its width and horizontal positioning to avoid colliding with the operating system's window controls, regardless of the platform.
Restoring Window Dragging Functionality
When the standard system title bar is removed, the user loses the
default area used to click and drag the application window around the
screen. To fix this, developers must use the
-webkit-app-region CSS property.
By applying -webkit-app-region: drag; to the custom
title bar container, the entire custom header becomes a draggable handle
for the window. However, if the custom title bar contains interactive
elements—such as a search input, a profile button, or navigation
links—the user will not be able to click them if they are set to drag.
Developers must explicitly apply
-webkit-app-region: no-drag; to those specific interactive
child elements so they remain clickable while the background around them
remains draggable.
Detecting State with JavaScript
The Window Controls Overlay is not always active; a user can toggle
it off using a button in the title bar, or the app might be running on a
mobile device where the feature is unsupported. Chromium provides the
navigator.windowControlsOverlay JavaScript API to handle
this dynamically.
Developers can check the
navigator.windowControlsOverlay.visible boolean property to
see if the overlay is currently active and adjust the app's layout
accordingly. Additionally, the API provides a
getTitlebarAreaRect() method to query the exact pixel
dimensions of the available space in JavaScript, and a
geometrychange event listener that fires whenever the user
toggles the overlay or resizes the window.