Skip to content

Manifest · Manifest member

theme_color and background_color manifest members

Published

Limited availabilityNot supported in Firefox (Desktop), Firefox (Desktop), Safari (macOS), Safari (iOS)W3C draft

theme_color is the colour the operating system and browser use for the chrome around an installed app: the title bar on desktop, the status bar and task-switcher card on Android, and the accent of the install dialog. background_color is the colour painted behind the app icon on the splash screen and inside the window from launch until the page’s own CSS has painted. The two members exist so that nothing white flashes between the icon tap and the first frame.

Chrome 46, Edge 79, Samsung Internet 5.0, Android WebView 46, and Firefox 79 on Android read both members; Safari reads theme_color from iOS 15 and macOS 17 but has no consumer for background_color (BCD html.manifest.theme_color and html.manifest.background_color). Desktop Firefox installs no apps from the manifest and uses neither.

  • Type: string holding a CSS <color>: a named colour, hex, rgb(), hsl(), or any other form the engine’s CSS parser accepts. Chromium stores the parsed value as an opaque colour, so an alpha channel is discarded.
  • Default: absent. With no theme_color the engine uses its own chrome colour; with no background_color the splash screen is white (Chromium) or the system background.
  • Example value: "theme_color": "#1a1a2e", "background_color": "#1a1a2e".

A value the CSS parser rejects is dropped with property 'theme_color' ignored, 'bluish' is not a valid color. (the same message names background_color), and the member then behaves as absent (manifest_parser.cc).

The manifest value is the colour of record only until a page is showing. Once loaded, a <meta name="theme-color"> element in the document overrides theme_color for that page, and because the element accepts a media attribute the page can declare one colour per colour scheme, which the manifest cannot (MDN, <meta name="theme-color">). Chromium reads background_color only for the splash screen and the pre-paint window fill, so the page’s body background must be set to the same value or a visible colour step appears at first paint.

The examples share one dark-navy brand colour, #1a1a2e, and a light variant, #f5f5fa.

One manifest colour, two page colours for light and dark mode

Section titled “One manifest colour, two page colours for light and dark mode”

The manifest carries the colour used before any page exists, so it holds the default scheme. The two <meta> elements take over once the page loads and switch with the user’s system setting.

{
"theme_color": "#1a1a2e",
"background_color": "#1a1a2e"
}
<meta name="theme-color" content="#f5f5fa" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#1a1a2e" media="(prefers-color-scheme: dark)">

On Android the status bar follows the matching <meta> as soon as the page paints; during the splash screen it shows the manifest value regardless of the scheme.

A splash screen that hands off without a colour step

Section titled “A splash screen that hands off without a colour step”

Chromium composes the splash from background_color, the largest icons entry, and name. Setting the document background to the same colour, before any stylesheet that might load late, keeps the handoff from splash to page invisible.

:root {
color-scheme: dark;
background: #1a1a2e;
}
@media (prefers-color-scheme: light) {
:root {
background: #f5f5fa;
}
}

A light-scheme user still sees the navy splash, because the manifest has one value; the step from navy to #f5f5fa happens at first paint and lasts one frame, which is the trade-off for not shipping two manifests.

Keeping the live theme colour and the page in sync

Section titled “Keeping the live theme colour and the page in sync”

Nothing at runtime reports which colour the OS chrome adopted, so the page reads back its own active <meta> element and uses that value for in-page surfaces such as a sticky header. When no element matches, the code falls back to the manifest’s documented colour.

function activeThemeColor() {
const dark = matchMedia('(prefers-color-scheme: dark)').matches;
const metas = [...document.querySelectorAll('meta[name="theme-color"]')];
const match = metas.find((m) => !m.media || matchMedia(m.media).matches === true);
return match?.content ?? (dark ? '#1a1a2e' : '#f5f5fa');
}
document.querySelector('header').style.background = activeThemeColor();
matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
document.querySelector('header').style.background = activeThemeColor();
});

The listener matters on desktop, where the user can flip the system scheme while the app is open; the OS title bar updates by itself, and this keeps the header with it.

Specifications

SpecificationStatus
Web App Manifest: theme_color / background_colorW3C draft
Web Application Manifest: theme_color memberW3C
Web Application Manifest: background_color memberW3C
  • Legend
  • Yes
  • Partial
  • Flag
  • No
  • Unknown
Browser / PlatformSupportVersionsConfidenceSourceNotes
Chrome (Desktop)Yes46highsource1
Chrome (Android)Yes46highsource23
Edge (Desktop)Yes79highsource45
Firefox (Desktop)No—highsource67
Firefox (Android)Yes79highsource8
Safari (macOS)Yes17highsource9
Safari (iOS)Yes15highsource10
Samsung InternetYes5.0highsource1112
WebView (Android)Yes46highsource1314
Chrome (Desktop)Yes46highsource15
Chrome (Android)Yes46highsource1617
Edge (Desktop)Yes79highsource1819
Firefox (Desktop)No—highsource2021
Firefox (Android)Yes79highsource22
Safari (macOS)No—highsource2324
Safari (iOS)No—highsource252627
Samsung InternetYes5.0highsource2829
WebView (Android)Yes46highsource3031
  1. Covers the `theme_color` entry.
  2. Covers the `theme_color` entry.
  3. Derived by browser-compat-data mirroring from Chrome.
  4. Covers the `theme_color` entry.
  5. Derived by browser-compat-data mirroring from Chrome.
  6. Covers the `theme_color` entry.
  7. No Firefox support is recorded in browser-compat-data.
  8. Covers the `theme_color` entry.
  9. Covers the `theme_color` entry.
  10. Covers the `theme_color` entry.
  11. Covers the `theme_color` entry.
  12. Derived by browser-compat-data mirroring from Chrome Android.
  13. Covers the `theme_color` entry.
  14. Derived by browser-compat-data mirroring from Chrome Android.
  15. Covers the `background_color` entry.
  16. Covers the `background_color` entry.
  17. Derived by browser-compat-data mirroring from Chrome.
  18. Covers the `background_color` entry.
  19. Derived by browser-compat-data mirroring from Chrome.
  20. Covers the `background_color` entry.
  21. No Firefox support is recorded in browser-compat-data.
  22. Covers the `background_color` entry.
  23. Covers the `background_color` entry.
  24. No Safari support is recorded in browser-compat-data.
  25. Covers the `background_color` entry.
  26. No Safari on iOS support is recorded in browser-compat-data.
  27. Derived by browser-compat-data mirroring from Safari.
  28. Covers the `background_color` entry.
  29. Derived by browser-compat-data mirroring from Chrome Android.
  30. Covers the `background_color` entry.
  31. Derived by browser-compat-data mirroring from Chrome Android.

Source data: /compatibility/manifest-theme-background-color.json · Global usage: 83 % (StatCounter 2026-05)

Source: spec · MDN · Last verified 2026-10-03 · Confidence: high (computed from sources)