pavel 1ar.ionov

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-color on the element itself
  • backdrop-filter on 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: absolute children of fixed elements — ignored entirely
  • Pseudo-elements (::before, ::after) — invisible to the tinting algorithm
  • theme-color meta 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: 0 elements — a fixed element with opacity: 0 still has its background-color and backdrop-filter parsed. Invisible doesn’t mean ignored
  • pointer-events: none elements — 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 also position: 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

  1. Viewport meta: viewport-fit=cover — required for bottom bar transparency
  2. html background: set explicitly — Safari uses it as fallback
  3. Fixed header: background-color: transparent, no backdrop-filter on the fixed element itself. Glass effect on an absolute child
  4. Hidden overlays: display: none when inactive, not just opacity: 0
  5. theme-color: still fine to set for older browsers, but Safari 26 ignores it
  6. Layout padding: account for env(safe-area-inset-top) and env(safe-area-inset-bottom) since viewport-fit=cover extends 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