eleven / messenger Public

Fix mobile keyboard layout: size chat to visualViewport; bottom-anchor messages

The chat used height:100%, which doesn't shrink when the on-screen keyboard opens,
so content scrolled out of view. Now sized to --app-height (tracked from
window.visualViewport, with a 100dvh fallback), and #feed::before margin-top:auto
keeps a few messages pinned just above the composer.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Paul Campbell 11cb9180ab8aa2d2be3a2157ff87ca1e2d53bb9b parent 0a05374
2 files changed, +19 −2
  • web/static/chat.js +12 −0
  • web/static/style.css +7 −2
diff --git a/web/static/chat.js b/web/static/chat.js
index 9f96200..b965e8f 100644
--- a/web/static/chat.js
+++ b/web/static/chat.js
@@ -16,6 +16,18 @@ const SESSION_KEY = "lchat_session";
const app = document.getElementById("app");
const session = loadSession();
+// Track the *visible* viewport height (it shrinks when the mobile keyboard opens)
+// so the chat fits above the keyboard instead of overflowing off-screen.
+function setAppHeight() {
+ const h = (window.visualViewport && window.visualViewport.height) || window.innerHeight;
+ document.documentElement.style.setProperty("--app-height", h + "px");
+}
+setAppHeight();
+window.visualViewport?.addEventListener("resize", setAppHeight);
+window.visualViewport?.addEventListener("scroll", setAppHeight);
+window.addEventListener("resize", setAppHeight);
+window.addEventListener("orientationchange", () => setTimeout(setAppHeight, 150));
+
route();
// Full-screen onboarding steps come before the chat feed: "Add to Home Screen"
diff --git a/web/static/style.css b/web/static/style.css
index 50a06a2..a89cff8 100644
--- a/web/static/style.css
+++ b/web/static/style.css
@@ -53,7 +53,7 @@ input:focus, textarea:focus { outline: 2px solid var(--accent); border-color: tr
/* ---- centered card layout (join / fallback) ---- */
.center {
- min-height: 100%;
+ min-height: var(--app-height, 100%);
display: grid;
place-items: center;
padding: 24px;
@@ -75,7 +75,7 @@ input:focus, textarea:focus { outline: 2px solid var(--accent); border-color: tr
.chat {
display: flex;
flex-direction: column;
- height: 100%;
+ height: var(--app-height, 100dvh);
max-width: 720px;
margin: 0 auto;
background: var(--panel);
@@ -151,6 +151,11 @@ input:focus, textarea:focus { outline: 2px solid var(--accent); border-color: tr
flex-direction: column;
gap: 4px;
}
+/* push a few messages to the bottom (near the composer); scrolls normally when full */
+#feed::before {
+ content: "";
+ margin-top: auto;
+}
.msg { display: flex; flex-direction: column; max-width: 78%; margin-top: 10px; }
.msg .name { font-size: 12px; color: var(--muted); margin: 0 6px 3px; }
.msg .bubble {