Optimize the web app for iOS 26 Safari (Liquid Glass) — safe areas, toolbar tinting, viewport
Why¶
iOS 26 Safari (Sept 2025) redesigned its chrome as Liquid Glass: the bottom tab bar and toolbars now
FLOAT OVER the page, tint themselves by sampling the page's own fixed/sticky elements near the viewport
edges (+ theme-color), and let content scroll behind them. The owner reports the app's bottom
sidebar/nav "turned into liquid-glass and sort of expanded" on iPhone — the classic symptom of Safari
merging its floating bar with the app's own fixed bottom element. Apple shipped this with next to no
web-developer documentation; the community mapped the rules (sources below).
Research summary (2026-07-03)¶
viewport-fit=coveris the prerequisite — without itenv(safe-area-inset-*)stays 0 and the bottom-bar transparency behaves inconsistently. Today only the signing pages set it (app/ir56m/sign/**,app/wopc/sign/**viaviewport.viewportFit); the app shell does not.- Fixed/sticky elements near the top/bottom edge must NOT carry
background-colororbackdrop-filteron the fixed element itself — Safari samples them for toolbar tinting and visually merges/expands its bar with the element. Put the visual background on an absolute child. - Hidden fixed overlays must use
display:nonewhen closed —opacity:0+pointer-events:nonestill feeds Safari's tint sampler. - Set an explicit
background-coloronhtml/body— Safari derives bar tint from the root color; unset roots cause white/black bar flashes and wrong tints. - Audit
theme-colormeta — participates in top/bottom bar tinting on iOS 26. - Viewport-height audit —
100vhtraps under the dynamic toolbar; usedvh/svh(T-120 did the signing pages; the rest of the app is unaudited). - Fixed bottom UI must add
env(safe-area-inset-bottom)padding/offset so it clears the floating bar (the build watermark now does this — see the shipped starter below).
Scope¶
- App-wide
viewport-fit=cover(App Router rootviewportexport + Pages Router meta) with a safe-area padding audit of every fixed edge element (bottom nav, drawers, FABs, toasts) — the two must land together or content sits under the home indicator. - Fix the mobile bottom nav ("sidebar at the bottom"): safe-area inset + move any background/backdrop-filter off the fixed element per rule #2 (kills the "expanded liquid-glass" look).
- Root
html/bodyexplicit background +theme-coloraudit (light/dark). 100vh→dvh/svhsweep beyond T-120.- Overlay audit: closed fixed overlays render
display:none. - Device test matrix: iPhone Safari 26, portrait/landscape, bottom-tab-bar vs compact setting.
- Auth on iOS Safari (absorbed from T-083, 2026-07-09): the popup-blocked
signInWithRedirectfallback breaks under storage partitioning with the cross-domainauthDomain(aote-pms.firebaseapp.com) — fix per T-083's design: same-origin authDomain via a reverse-proxied/__/authon eop.theestablishers.com.
Sources¶
- WebKit Features in Safari 26.0
- Safari 26 Liquid Glass: toolbar tinting, white bars, viewport bugs (1ar.io)
- iOS26 Safari theme-color/tab-tinting with fixed position elements (Ben Frain)
- iOS 26.0 — Be prepared for viewport changes in Safari (stripearmy)
- How Safari in iOS 26 puts content first with Liquid Glass (AppleInsider)
Decision log¶
2026-07-03 — opened; starter shipped (build watermark)¶
- ✅ Read AGENTS.md. Opened at the owner's request (verbatim): "please research on the specification of the most updated iOS safari browser so that not just for build number rendering, the optimize the web app in general specifically for iOS safari (it's a big task, so create a task UID for it, but start with the build number rendering first)". Board scope-checked — nearest neighbors are T-120 (dvh on signing pages only) and mobile.css work; nothing covers the iOS-26 Liquid-Glass adaptation.
- Starter shipped (same commit):
components/BuildWatermark.tsx— desktop moved 5px further left (right:10px, owner request), touch devices lift the stamp above the liquid-glass bar viaenv(safe-area-inset-bottom)(fully effective app-wide once scope #1 landsviewport-fit=cover). - UID note: the README next-free pointer was stale at T-150 while T-150–T-153 had all been taken by parallel agents without bumps (T-150 badges editor #853, T-151 two-layer RBAC, T-152 quotation delete, T-153 invoice line-discount). Took the real next-free T-154; pointer set to T-155.
- Source: EOP Local Assistance (fork) · session edb0abc7-6373-449b-8e31-379fd38d391b