Safari 26 Liquid Glass: fixing toolbar tinting for web developers
How Safari 26 derives toolbar colors from your CSS, and how to prevent unwanted status bar and bottom bar tinting.
Safari 26 no longer reads
theme-color. It reads your CSS — and it’s pickier than you’d expect.
With Liquid Glass, Apple redesigned every toolbar and status bar to be translucent. Safari’s browser chrome now derives its tint from the web page itself. If your fixed header has a background color, your status bar will match it. If a hidden modal backdrop sits at the bottom of the viewport, your bottom toolbar will turn dark.
No documentation from Apple explains the exact rules. Here’s what I’ve found through trial and error while building 1ar.io.
The tinting algorithm
Safari 26 scans for position: fixed or position: sticky elements near the viewport edges and reads two properties:
background-coloron the element itselfbackdrop-filteron the element itself
It uses these to compute the tint color for the nearest toolbar (status bar at the top, Safari toolbar at the bottom).
What Safari does NOT sample
position: absolutechildren of fixed elements — ignored entirely- Pseudo-elements (
::before,::after) — invisible to the tinting algorithm theme-colormeta tag — Safari 26 ignores it completely. It was the old mechanism; now tinting is purely CSS-derived- Non-fixed elements — regular flow content, even if visually near the edge, doesn’t affect tinting
What Safari DOES sample (even when you don’t expect it)
opacity: 0elements — a fixed element withopacity: 0still has itsbackground-colorandbackdrop-filterparsed. Invisible doesn’t mean ignoredpointer-events: noneelements — same as above. The element exists in the render tree, Safari reads its styles- Elements inside fixed parents that themselves have
position: fixed— if a child inside your fixed header is alsoposition: fixed, Safari evaluates it independently
This means hidden overlay backdrops, modal containers, and dropdown panels — the kind that sit in the DOM as opacity: 0; pointer-events: none until toggled — will affect toolbar tinting unless you also use display: none.
Fixing the top bar (status bar)
The status bar tints based on fixed elements within ~4px of the viewport top. A typical glassmorphism header breaks this immediately:
<!-- broken: Safari tints status bar with header's bg + blur -->
<header style="position: fixed; top: 0;
background-color: rgba(255,255,255,0.8);
backdrop-filter: blur(12px);">
</header>
The fix: transparent parent, absolute child
Move all visual properties to a position: absolute child. Safari sees the fixed parent as transparent and ignores the absolute child.
<header style="position: fixed; top: 0;
background-color: transparent;">
<!-- Safari ignores this because it's position:absolute -->
<div style="position: absolute; inset: 0;
background-color: rgba(255,255,255,0.8);
backdrop-filter: blur(12px);"
aria-hidden="true">
</div>
<!-- nav content, z-index above the glass -->
<nav style="position: relative; z-index: 1;">...</nav>
</header>
The header stays transparent — no background-color, no backdrop-filter on the fixed element itself. The glass effect lives on a child div that Safari’s tinting algorithm skips.
Fixing the bottom bar (Safari toolbar)
The bottom bar follows the same logic but with an extra requirement: viewport-fit=cover.
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
Without viewport-fit=cover, the page content stops at the safe area boundary. Safari renders a solid bar in the gap between your content and the toolbar. With viewport-fit=cover, content extends behind the toolbar, giving Liquid Glass something to show through.
You also want the html element to declare its background explicitly:
html {
background-color: var(--your-page-bg);
}
Safari falls back to the html or body background when no qualifying fixed element is found near the bottom. If you don’t set it, the fallback is white (light) or black (dark) — which looks like a solid bar.
Hidden fixed elements break the bottom bar
This is the subtle one. If you have a modal backdrop like this:
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(2px);
opacity: 0;
pointer-events: none;
}
It spans the entire viewport including the bottom edge. Safari reads its background-color and backdrop-filter — even at opacity: 0 — and tints the bottom toolbar dark.
The fix: display none when hidden
.modal-backdrop {
display: none; /* completely removed from render tree */
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(2px);
}
.modal-backdrop.is-open {
display: block;
opacity: 1;
}
When the element uses display: none, it doesn’t exist in the render tree. Safari can’t sample it. Toggle to display: block when you need it, and Safari will tint the toolbar accordingly (which is correct — when a modal is open, you want the toolbar to reflect the overlay).
If you need an opacity transition, set display: block first via JavaScript, then add the opacity class in the next animation frame:
function openModal() {
backdrop.style.display = 'block';
requestAnimationFrame(() => {
backdrop.classList.add('is-open');
});
}
function closeModal() {
backdrop.classList.remove('is-open');
setTimeout(() => {
backdrop.style.display = 'none';
}, 200); // match CSS transition duration
}
Quick checklist
- Viewport meta:
viewport-fit=cover— required for bottom bar transparency htmlbackground: set explicitly — Safari uses it as fallback- Fixed header:
background-color: transparent, nobackdrop-filteron the fixed element itself. Glass effect on anabsolutechild - Hidden overlays:
display: nonewhen inactive, not justopacity: 0 theme-color: still fine to set for older browsers, but Safari 26 ignores it- Layout padding: account for
env(safe-area-inset-top)andenv(safe-area-inset-bottom)sinceviewport-fit=coverextends content into safe areas
Known issues
Safari’s tinting behavior with fixed elements has been filed as WebKit Bug #302272 (duplicate of #300965). Safari 26.2 fixed fullscreen dialog backdrops not extending below the address bar, but the general fixed-element tinting behavior appears to be by design rather than a bug — it’s how Liquid Glass is supposed to work. Web developers just need to account for it.
Ben Frain has a detailed write-up on the same issue, focused on dialog and popover elements.
Further reading
- How Liquid Glass works — displacement maps, 2D refraction, and gyroscope tricks
- What’s new in Safari and WebKit — WWDC25 — official session (doesn’t cover tinting, but covers new CSS features)
- WebKit features in Safari 26.0 — release notes