fix(mobile): stop iOS zooming the page when a field is focused

iOS WebKit zooms the whole page when a focused form control computes to
under 16px. `#messageInput` was 0.9rem (14.4px) on narrow screens, so
every tap on the message box tripped it - reported on iPhone in both
Safari and Chrome, on a phone with no configuration of its own.

The zoom also never undid itself: the shell is `height: 100dvh;
overflow: hidden`, so WebKit has nothing to scroll back and leaves the
page scaled until the user pinches out.

Raise every focusable control to 16px on (pointer: coarse), which also
covers landscape phones wider than the 768px breakpoint. Desktop keeps
Bootstrap's smaller sizing. The guard uses !important on purpose: it has
to outrank page-local <style> blocks that load after style.css and reach
specificities like `.filter-sort-toolbar .form-select`.

Fields that only open a picker (checkbox, radio, range, color, file,
buttons) are excluded - they never trigger the zoom.

The contacts toolbar was the one layout that could not take the bump:
three 16px selects overflow one unwrapped flex row, clipping the sort
control, so it now wraps.

Verified locally at 390x844 and 932x430 with touch emulation: no control
under 16px on any route, no horizontal overflow, desktop unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
MarekWoandClaude Opus 5 committed 2026-08-14 11:34:38 +02:00
1 parent e848bc16a4
commit 8ce57f2868
3 files changed
+42 -3

No files matched your search

+37 -3
View File
@@ -566,9 +566,11 @@ main {
max-width: 85%;
}
/* Chat inputs stay at 16px on mobile - anything smaller makes iOS zoom the
whole page on focus. See "iOS auto-zoom guard" at the end of this file. */
#messageInput,
#dmMessageInput {
font-size: 0.9rem;
font-size: 16px;
}
/* Reduce padding on mobile to save vertical space */
@@ -610,10 +612,10 @@ main {
font-size: 0.9rem;
}
/* DM: Contact search input on mobile */
/* DM: Contact search input on mobile (16px - see iOS auto-zoom guard) */
#dmContactSearchInput {
min-width: 100px !important;
font-size: 0.9rem;
font-size: 16px;
}
/* Navbar: Smaller buttons */
@@ -2278,3 +2280,35 @@ emoji-picker {
font-size: 0.8rem;
padding: 0.25rem 0.75rem;
}
/* =============================================================================
iOS auto-zoom guard - KEEP THIS BLOCK LAST
-----------------------------------------------------------------------------
iOS WebKit (Safari, and Chrome/Firefox on iOS, which are WebKit too) zooms the
entire page when a focused form control has a computed font-size below 16px.
Because our shell is `height: 100dvh; overflow: hidden`, WebKit has nothing to
scroll back and leaves the page scaled - the user has to pinch out manually.
So: every focusable control stays at >= 16px on touch devices. Make controls
compact with padding/rows, never with font-size.
Scoped to (pointer: coarse) rather than a width breakpoint on purpose: it also
covers landscape phones, which are wider than 768px but still zoom. Desktop
keeps Bootstrap's smaller sizing.
`!important` is deliberate. This is a hard floor, and it has to outrank rules
it cannot enumerate: page-local <style> blocks load after this file and reach
specificities like `.filter-sort-toolbar .form-select` (contacts_base.html) or
`.filter-select` (logs.html). Being hard to override is the point - a new page
that shrinks its inputs should not silently bring the zoom back.
Types that open a picker rather than a keyboard are excluded: they never
trigger the zoom, so there is no reason to change how they look.
============================================================================= */
@media (pointer: coarse) {
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="button"]):not([type="submit"]):not([type="reset"]),
select,
textarea {
font-size: 16px !important;
}
}
+1
View File
@@ -146,6 +146,7 @@
/* Sort toolbar */
.filter-sort-toolbar {
display: flex;
flex-wrap: wrap; /* 16px selects on touch (iOS zoom guard) overflow one row */
gap: 0.375rem;
margin-bottom: 1rem;
align-items: center;
+4
View File
@@ -10,6 +10,10 @@ For deep technical notes, see [architecture.md](architecture.md). For the full g
## Unreleased
### Fixes
- **On an iPhone, tapping a text field no longer blows the whole page up.** Tap the message box, and the page zoomed in — the send button pushed off the right edge, the layout too wide for the screen — and it stayed that way after the keyboard was dismissed, until you pinched it back down by hand. It happened in Safari and in Chrome, on a freshly unboxed phone with nothing configured, and it was not the phone's fault: iPhones deliberately zoom in on a form field whose text is smaller than 16 pixels, on the assumption that you would otherwise be squinting at it. The message box was set to 14.4 pixels on narrow screens, so every tap tripped it. Worse, the app's layout is pinned to the height of the screen and does not scroll as a page, which leaves the browser nothing to scroll back — so the zoom stuck instead of undoing itself. Every text field, dropdown and search box in the app is now at least 16 pixels on a touch screen, which is the size iPhones are content to leave alone. iPads never did this, and Android phones never did either, which is why it went unnoticed for so long. On a computer the fields are unchanged.
---
## 2.9.0 — 2026-08-14