Skip to content

Display and Theme

Controlling how the app looks after installation

Section titled “Controlling how the app looks after installation”

Once a user installs your PWA, the manifest fields in this lesson determine whether the app looks like a native app or still shows browser UI — and how it integrates with the OS at the visual level.

The display field sets the preferred display mode for the app window:

ValueBrowser UIUse case
standaloneNo address bar, minimal OS chromeMost apps — feels native
fullscreenNo browser UI at allGames, immersive experiences
minimal-uiBack/forward/reload buttons onlyContent viewers, media players
browserFull browser UIFallback — same as a normal tab
{ "display": "standalone" }

display_override is an ordered preference list. The browser picks the first value it supports, then falls back to display. Use it to request newer modes like window-controls-overlay (a title-bar extension) on browsers that support it:

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

theme_color colours the browser’s toolbar and the task switcher tile on Android. Set it to your brand’s primary colour. You can also set it per-page with <meta name="theme-color"> — the meta tag overrides the manifest for that page.

background_color is the colour shown during the splash screen (the brief flash between tapping the icon and the app’s first render). Set it to match your app’s background so the transition feels seamless.

{
"theme_color": "#5A0FC8",
"background_color": "#ffffff"
}
flowchart TD
  A["Browser reads display_override list"] --> B{"Supports first value?"}
  B -->|"Yes"| C["Use that display mode"]
  B -->|"No"| D{"More items in override list?"}
  D -->|"Yes"| A
  D -->|"No"| E["Fall back to display field"]
  E --> F{"display value supported?"}
  F -->|"Yes"| G["Use display value"]
  F -->|"No"| H["Use browser (default)"]
How the browser selects a display mode

orientation locks the screen orientation when the PWA is running. Common values: "portrait", "landscape", "any", "natural". Omit it to let the user rotate freely.

{ "orientation": "portrait" }

categories is an array of strings hinting to app directories and OS stores what type of app this is. There is no fixed spec-required vocabulary, but common values mirror Play Store categories: "productivity", "utilities", "games", "finance", etc.

{ "categories": ["productivity", "utilities"] }

screenshots provides images shown in install dialogs on browsers and OS stores that support them. Each entry has src, sizes, type, and an optional form_factor ("narrow" for mobile, "wide" for desktop).

{
"screenshots": [
{
"src": "/screenshots/home-narrow.png",
"sizes": "390x844",
"type": "image/png",
"form_factor": "narrow",
"label": "Home screen on mobile"
},
{
"src": "/screenshots/home-wide.png",
"sizes": "1280x800",
"type": "image/png",
"form_factor": "wide",
"label": "Home screen on desktop"
}
]
}

Chrome on desktop requires at least one screenshot before it shows the rich install dialog with a preview panel.

OptionBenefitCost
display: "standalone"Feels fully native, no browser UIUsers lose the familiar back/forward buttons and address bar
display: "browser"Keeps normal browser behaviour, instantly familiarLoses the “app” feeling the install prompt promised
  • Setting theme_color in the manifest only, without also setting <meta name="theme-color">, so colors mismatch between browser UI and standalone mode.
  • Choosing display: "fullscreen" for an ordinary app, so users lose the status bar and gesture navigation they rely on.
  • Not testing the theme in dark mode, so the background/theme colors clash with the user’s system colors.

Twitter Lite tuned its theme_color to match its brand color as part of its PWA rebuild, so the status bar blends with the UI the moment it is opened from the home screen (web.dev/twitter).

Which display value removes all browser UI to create a fully immersive experience?
What is the purpose of background_color in the manifest?
How does display_override work when the browser does not support its first value?
Which manifest field hints to app stores about the category of your app?