Skip to content

display_override: opting into window-controls-overlay and tabbed modes

In one line: display can only express the four values on its fixed fallback chain (fullscreenstandaloneminimal-uibrowser). display_override is an ordered array the browser walks before falling back to display, so it’s how you opt into newer modes like window-controls-overlay and tabbed without losing a safe fallback on browsers that don’t support them.

display is a single value confined to one chain. There’s no way to say “use window-controls-overlay if you can, otherwise behave like standalone” with display alone, because window-controls-overlay isn’t on the chain. display_override solves this: it lets you list preferred modes in priority order, and the browser uses the first one it both recognizes and supports.

{
"display": "standalone",
"display_override": ["window-controls-overlay", "minimal-ui"],
"scope": "/app/",
"start_url": "/app/"
}

The browser evaluates display_override strictly in order, then falls back to display:

  1. Walk display_override left to right. Use the first entry that is a valid, supported display mode.
  2. If no entry matches (all unknown or unsupported), ignore display_override entirely and fall back to the plain display value and its normal chain.

Two consequences follow from this:

  • Unknown entries are skipped, not fatal. An older browser that has never heard of window-controls-overlay simply moves to the next entry, so the manifest degrades gracefully instead of breaking.
  • display_override does not inherit the display fallback chain. Listing ["fullscreen"] does not automatically fall through to standalone the way display: "fullscreen" does. Within the override array each entry is considered on its own; the chain only resumes once the browser drops to the display value.
  • window-controls-overlay — on desktop, the app’s web content extends up into the title-bar area, and the window controls (close/minimize/maximize) overlay your content. You get the full window height for a custom toolbar. Use the titlebar-area-* environment variables and the navigator.windowControlsOverlay API to lay out a region that stays clear of the OS controls.
  • tabbed — gives an installed app its own in-app tab strip so users can keep multiple app pages open inside one application window. Support is narrower and still evolving.
  • standalone / minimal-ui / fullscreen / browser — the ordinary display values are also legal inside display_override, which is useful purely as an explicit fallback entry before the implicit display fallback kicks in.

The modes you can list inside display_override are still experimental and have limited support, and they differ from one another. The cited MDN references mark window-controls-overlay and the newer display modes as experimental and direct you to each feature’s browser-compatibility table — treat those tables as the source of truth before relying on a mode, and always pair any override with a display value that is widely supported.

display_override, installability, and scope

Section titled “display_override, installability, and scope”
  • Installability counts display_override too. Per MDN’s installability guide, Chromium-based browsers require the manifest to include display and/or display_override, so listing override modes can itself satisfy that part of the criteria. Still keep a display value that launches an app-style window for the broadest coverage.
  • Scope still bounds the chrome treatment. When the user navigates outside scope, the browser typically surfaces a prominent UI element (such as the address bar) to signal the context. Nothing forces an app context to stay in scope, but the overlay or tab strip is intended for the in-scope app launched from start_url.
  • Set a safe display (usually standalone) so installability and old browsers are covered.
  • List override modes in true priority order — the first supported entry wins.
  • Don’t rely on display_override to fall through its own list like display does.
  • For window-controls-overlay, use the titlebar-area-* env vars and the API to lay content out clear of the window controls; test the case where the overlay isn’t granted.
  • Feature-detect navigator.windowControlsOverlay before assuming the overlay is active.
  • Treat tabbed as progressive enhancement; verify behavior on each target browser.