iOS status bar colour and geometry
Published
An installed web app on iOS can colour the strip behind the status icons and can extend its CSS viewport beneath that strip. On an iPhone 16 Pro running iOS 18.6.2, the page’s theme-color meta supplied the colour when present, while black-translucent together with viewport-fit=cover exposed a full-height viewport and a top safe-area inset.
Use these steps when you need to reproduce that measured configuration or separate a colour problem from a safe-area problem. You need an HTTPS page with a web app manifest, an iPhone that can add it to the Home Screen, and Mac Safari Web Inspector for the instrumented geometry read. The numerical results below apply to the recorded iPhone 16 Pro and iOS 18.6.2 (22G100) run on 2026-10-20 (study data package, openpwa.net).
Where it is supported
Section titled “Where it is supported”The measured result applies to Safari and an installed Home Screen web app on an iPhone 16 Pro running iOS 18.6.2. WebKit introduced theme-color in HTML meta tags and web manifests for Safari 15 and says it changes the status-bar and overscroll colours in Safari on iOS 15 (New WebKit Features in Safari 15, webkit.org). The Web Application Manifest permits a document’s theme-color meta to override the manifest’s theme_color, but does not require that choice (Web Application Manifest, theme_color, w3.org).
The precedence and dimensions in this field note are measured iOS 18.6.2 results and do not describe every iOS release. The run did not install separate apps using the default or black values, did not test landscape or Dark appearance, and tested black-translucent only with viewport-fit=cover.
Examples
Section titled “Examples”Use one colour probe and one geometry probe to keep the rendered colour separate from the viewport measurement.
Declare both colour sources
Section titled “Declare both colour sources”Give the document a colour and keep the manifest colour as its default. The recorded M1 app used different values so the screenshot identified which declaration won.
<head> <meta name="theme-color" content="#00a050"> <link rel="manifest" href="/manifest.webmanifest"></head>{ "name": "Status bar probe", "start_url": "/", "display": "standalone", "theme_color": "#d00000"}Add the page from Safari, launch it from its Home Screen icon, and take a screenshot. In the recorded M1 result, all sampled points in the strip were #00a050; M2 used the meta value #d00000 without a manifest colour, and M3 used the manifest value #00a050 when the document had no meta. The result was that the document meta took precedence and the manifest value acted as the fallback on this build (status-bar colour source).
Detect the declarations before interpreting a visual mismatch. This check reports which source is available and gives an explicit fallback when neither exists.
const meta = document.querySelector('meta[name="theme-color"]');const manifestLink = document.querySelector('link[rel="manifest"]');
if (meta?.content) { console.log({ source: 'document', colour: meta.content });} else if (manifestLink) { console.log({ source: 'manifest', href: manifestLink.href });} else { console.log({ source: 'none', action: 'use browser default' });}For the M1 document, the command’s expected output is { source: "document", colour: "#00a050" }. It detects declarations only; use a screenshot or a device test to inspect the rendered strip.
Extend content under the status bar
Section titled “Extend content under the status bar”Apple’s archived meta-tag reference says black-translucent displays web content over the entire screen, partially obscured by the status bar, and that the setting affects a full-screen web app (Supported Meta Tags, developer.apple.com). Pair it with viewport-fit=cover, then use the safe-area environment variables to keep controls out of the obscured region. CSS defines the safe-area inset variables from the viewport edges, and cover uses the rectangle that circumscribes the screen (CSS Environment Variables, csswg.org; CSS Round Display, viewport-fit, csswg.org).
<meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"><meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"><style> .app-header { padding-top: env(safe-area-inset-top, 0px); padding-left: env(safe-area-inset-left, 0px); padding-right: env(safe-area-inset-right, 0px); }</style>The fallback arguments keep the padding at 0px when a browser does not expose an inset value. In the recorded Home Screen app, this configuration returned a 402 x 874 inner viewport, a 62 px top inset, and a 34 px bottom inset. The default-style comparison returned 402 x 812 with a zero top inset; adding viewport-fit=cover to that comparison changed the bottom inset to 34 px but did not move its top edge (black-translucent geometry).
Measure the active geometry
Section titled “Measure the active geometry”Connect Web Inspector after the installed app is visible. Create a temporary fixed element so the computed style resolves the environment variables, then print the viewport and padding.
const probe = document.createElement('div');probe.style.cssText = [ 'position:fixed', 'padding-top:env(safe-area-inset-top, 0px)', 'padding-bottom:env(safe-area-inset-bottom, 0px)'].join(';');document.body.append(probe);
const style = getComputedStyle(probe);console.log([innerWidth, innerHeight, style.paddingTop, style.paddingBottom]);probe.remove();The archived iOS 18.6.2 app read printed [402, 874, "62px", "34px"]. The same URL in a Safari tab printed [402, 678, "0px", "0px"]. Check matchMedia('(display-mode: standalone)').matches or navigator.standalone before comparing your output; if both are false, install and launch the page from its icon, because the tab result is a different presentation context.
If the header sits below the status strip despite black-translucent, first inspect the parsed meta and viewport strings in the active document. If the page covers the strip but text or controls collide with status icons, keep the full-height viewport and apply env(safe-area-inset-top) to the content container. Record the device, OS build, orientation, meta values, viewport output, and a screenshot so the result remains tied to the tested configuration.