diff --git a/app/static/css/app.css b/app/static/css/app.css index a08de56..42563b0 100644 --- a/app/static/css/app.css +++ b/app/static/css/app.css @@ -313,7 +313,8 @@ ul { /* ── App layout (vault) ──────────────────────────────────────────── */ .vault-page { height: 100vh; - height: 100dvh; + height: -webkit-fill-available; + height: calc(var(--vh, 1vh) * 100); overflow: hidden; } @@ -850,7 +851,7 @@ ul { width: 100%; max-width: 480px; max-height: 90vh; - max-height: 90dvh; + max-height: calc(var(--vh, 1vh) * 90); overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 28px; @@ -1457,8 +1458,8 @@ ul { @media (max-width: 768px) { .app-layout { flex-direction: column; - height: 100%; - min-height: 100dvh; + height: calc(var(--vh, 1vh) * 100); + min-height: calc(var(--vh, 1vh) * 100); overflow: hidden; } @@ -1474,8 +1475,10 @@ ul { left: 0; bottom: 0; width: 280px !important; + height: 100% !important; /* Chrome needs explicit height on position:fixed */ z-index: 90; overflow-y: auto; + -webkit-overflow-scrolling: touch; transition: none; } .sidebar.mobile-open { @@ -1483,6 +1486,14 @@ ul { flex-direction: column; } + /* Cancel all collapsed-state overrides inside mobile sidebar */ + .sidebar.collapsed { + display: none !important; + } + .sidebar.collapsed.mobile-open { + display: flex !important; + } + /* Mobile sidebar: always show full expanded state */ .sidebar .sidebar-label { opacity: 1 !important; @@ -1570,7 +1581,7 @@ ul { } .modal { max-width: 100% !important; - max-height: 92dvh; + max-height: calc(var(--vh, 1vh) * 92); border-radius: 16px 16px 0 0; padding: 20px 16px; } diff --git a/app/static/js/vault.js b/app/static/js/vault.js index 56d185c..084c9da 100644 --- a/app/static/js/vault.js +++ b/app/static/js/vault.js @@ -2737,4 +2737,37 @@ const Vault = (() => { return { init }; })(); +/** + * Cross-browser viewport height fix. + * + * Problem: Chrome on Android uses a fixed `100vh` that includes the address bar, + * causing overflow when the bar is visible. Safari uses a collapsing bar model. + * `dvh` (dynamic viewport height) fixes this but only in Chrome 108+ / Safari 15.4+. + * + * Solution: Set `--vh` = 1% of window.innerHeight (the *actual* visible height). + * CSS uses `calc(var(--vh, 1vh) * 100)` instead of `100vh` everywhere. + * On resize (Chrome address bar show/hide, orientation change) we update --vh. + */ +(function setViewportHeight() { + function update() { + const vh = window.innerHeight * 0.01; + document.documentElement.style.setProperty("--vh", `${vh}px`); + } + update(); + // Use ResizeObserver for Chrome (fires on address bar show/hide) + if (window.ResizeObserver) { + new ResizeObserver(update).observe(document.documentElement); + } + // Fallback: listen to resize and orientationchange + window.addEventListener("resize", update, { passive: true }); + window.addEventListener( + "orientationchange", + () => { + // Small delay: orientation change fires before innerHeight updates + setTimeout(update, 100); + }, + { passive: true }, + ); +})(); + document.addEventListener("DOMContentLoaded", Vault.init);