Bug: chat header scrolls off-screen when mobile keyboard opens (should stay sticky, body should compress) #30

Open
opened 2026-05-09 09:58:29 +00:00 by mAi · 0 comments
Collaborator

Bug (m, PWA-Voice 2026-05-09 11:57)

"Das Paliad-Chat-Fenster, wenn die Paliad-Seite auf ist, reguliert sich auf dem Browser nicht vertikal, so dass wenn das Keyboard hochgeht, sich auch der Header des Chats nach oben verschiebt. Dabei sollte es sich komprimieren und der Header oben bestehen bleiben, wie bei anderen Chat-Apps auch."

Symptom

When the on-screen keyboard appears on a mobile browser (iOS Safari, Android Chrome), the whole Paliad chat layout scrolls upward so the header gets pushed off-screen. The chat body doesn't shrink to make room for the keyboard — instead the entire surface translates up.

Expected (matching WhatsApp / Telegram / iMessage / any modern mobile chat):

  • Header stays sticky at the top of the visible viewport
  • Chat body compresses vertically to whatever space remains between header and input
  • Input stays just above the keyboard
  • The latest messages remain visible (auto-scroll to bottom on layout change)

Likely cause

Mobile-web viewport semantics. Common roots:

  1. Layout uses 100vh / min-height: 100vh instead of 100dvh / 100svh. vh is the large viewport height (no keyboard reservation), so when the keyboard appears the page is bigger than the visible area and the header disappears off the top.
  2. Missing <meta name="viewport" content="..., interactive-widget=resizes-content"> — the default interactive-widget=overlays-content (Android Chrome since v108) makes the keyboard overlay rather than resize, leaving the layout unchanged but the chat input invisible.
  3. position: fixed / position: sticky on the wrong element, or stacking-context issues when the URL bar collapses.
  4. iOS Safari pre-VirtualKeyboard-API: needs JS workaround listening to visualViewport.resize + setting CSS custom property like --vvh and using that for the chat-container height.

Expected fix shape

For SvelteKit / vanilla web:

  • Replace 100vh with 100dvh (dynamic viewport, accounts for browser-chrome + keyboard).
  • Add <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content">.
  • Header: position: sticky; top: 0 inside a flex column container with height: 100dvh.
  • Body: flex: 1; overflow-y: auto — auto-shrinks when keyboard takes space.
  • Input: position: sticky; bottom: 0 (or bottom: env(keyboard-inset-height, 0) for newer browsers).
  • iOS Safari fallback: visualViewport JS listener that resizes the container manually. Common snippet:
import { visualViewport } from 'window';
visualViewport?.addEventListener('resize', () => {
  document.documentElement.style.setProperty('--vvh', `${visualViewport.height}px`);
});
// CSS: .chat-shell { height: var(--vvh, 100dvh); }

Reproduction

  • Open paliad.de (or wherever the chat surface lives) on a phone
  • Tap the message input → keyboard appears
  • Header gets pushed off-screen instead of staying fixed
  • m noticed this 2026-05-09 11:57

Out of scope

  • Desktop browsers (likely fine — this is mobile-only)
  • Native PWA install flow
  • Keyboard handling in the broader Paliad app (only the chat surface)

Acceptance criteria

  1. Open Paliad on iOS Safari → keyboard up → header stays at top of visible viewport, body shrinks, input above keyboard.
  2. Same on Android Chrome.
  3. Latest message stays visible (no manual scroll needed) when keyboard opens / closes.
  4. No regression on desktop or tablet landscape.

Refs

## Bug (m, PWA-Voice 2026-05-09 11:57) > "Das Paliad-Chat-Fenster, wenn die Paliad-Seite auf ist, reguliert sich auf dem Browser nicht vertikal, so dass wenn das Keyboard hochgeht, sich auch der Header des Chats nach oben verschiebt. Dabei sollte es sich komprimieren und der Header oben bestehen bleiben, wie bei anderen Chat-Apps auch." ## Symptom When the on-screen keyboard appears on a mobile browser (iOS Safari, Android Chrome), the **whole Paliad chat layout scrolls upward** so the header gets pushed off-screen. The chat body doesn't shrink to make room for the keyboard — instead the entire surface translates up. Expected (matching WhatsApp / Telegram / iMessage / any modern mobile chat): - Header stays sticky at the top of the *visible* viewport - Chat body **compresses** vertically to whatever space remains between header and input - Input stays just above the keyboard - The latest messages remain visible (auto-scroll to bottom on layout change) ## Likely cause Mobile-web viewport semantics. Common roots: 1. Layout uses `100vh` / `min-height: 100vh` instead of `100dvh` / `100svh`. `vh` is the *large* viewport height (no keyboard reservation), so when the keyboard appears the page is bigger than the visible area and the header disappears off the top. 2. Missing `<meta name="viewport" content="..., interactive-widget=resizes-content">` — the default `interactive-widget=overlays-content` (Android Chrome since v108) makes the keyboard overlay rather than resize, leaving the layout unchanged but the chat input invisible. 3. `position: fixed` / `position: sticky` on the wrong element, or stacking-context issues when the URL bar collapses. 4. iOS Safari pre-VirtualKeyboard-API: needs JS workaround listening to `visualViewport.resize` + setting CSS custom property like `--vvh` and using that for the chat-container height. ## Expected fix shape For SvelteKit / vanilla web: - Replace `100vh` with `100dvh` (dynamic viewport, accounts for browser-chrome + keyboard). - Add `<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content">`. - Header: `position: sticky; top: 0` inside a flex column container with `height: 100dvh`. - Body: `flex: 1; overflow-y: auto` — auto-shrinks when keyboard takes space. - Input: `position: sticky; bottom: 0` (or `bottom: env(keyboard-inset-height, 0)` for newer browsers). - iOS Safari fallback: `visualViewport` JS listener that resizes the container manually. Common snippet: ```js import { visualViewport } from 'window'; visualViewport?.addEventListener('resize', () => { document.documentElement.style.setProperty('--vvh', `${visualViewport.height}px`); }); // CSS: .chat-shell { height: var(--vvh, 100dvh); } ``` ## Reproduction - Open `paliad.de` (or wherever the chat surface lives) on a phone - Tap the message input → keyboard appears - Header gets pushed off-screen instead of staying fixed - m noticed this 2026-05-09 11:57 ## Out of scope - Desktop browsers (likely fine — this is mobile-only) - Native PWA install flow - Keyboard handling in the broader Paliad app (only the chat surface) ## Acceptance criteria 1. Open Paliad on iOS Safari → keyboard up → header stays at top of visible viewport, body shrinks, input above keyboard. 2. Same on Android Chrome. 3. Latest message stays visible (no manual scroll needed) when keyboard opens / closes. 4. No regression on desktop or tablet landscape. ## Refs - m's voice via PWA 2026-05-09 11:57 - MDN VisualViewport: https://developer.mozilla.org/en-US/docs/Web/API/VisualViewport - `interactive-widget` viewport meta: https://developer.chrome.com/blog/viewport-resize-behavior - m/mWeb#5 — meta-issue for filter / search / pagination conventions; this kind of mobile-keyboard handling probably belongs in the same convention doc once it gets written.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: m/paliad#30
No description provided.