Skip to content

fix(web): defense-in-depth against iOS Safari auto-zoom on input focus#2434

Open
alecramos-sudo wants to merge 1 commit intopingdotgg:mainfrom
alecramos-sudo:fix/ios-input-zoom-defense-in-depth
Open

fix(web): defense-in-depth against iOS Safari auto-zoom on input focus#2434
alecramos-sudo wants to merge 1 commit intopingdotgg:mainfrom
alecramos-sudo:fix/ios-input-zoom-defense-in-depth

Conversation

@alecramos-sudo
Copy link
Copy Markdown

@alecramos-sudo alecramos-sudo commented May 1, 2026

What Changed

Adds a global @media (hover: none) and (pointer: coarse) rule in apps/web/src/index.css that floors all <input>, <textarea>, <select>, and [contenteditable] elements to font-size: max(16px, 1em) on touch devices.

Why

#1652 (merged) patched two specific components — the chat composer and the sidebar thread-rename input — by switching to text-base sm:text-[14px]. That's a great per-component fix, but it leaves two failure modes open and #1265 remains reproducible:

  1. Other inputs are still vulnerable. Settings text fields, search bars (model picker, branch picker), filter inputs, and any future input added without the text-base sm: prefix silently re-introduce the bug. There's no linter rule to catch it. Confirmed in [Bug]: Focusing the chat input zooms the app in causing weird scroll on mobile #1265 by another user on a Samsung Galaxy S24 Ultra after fix(web): prevent iOS Safari auto-zoom on input focus #1652 was merged — same auto-zoom on a non-composer input.

  2. The sm: breakpoint is 640px, but iOS still auto-zooms past 640px. iPhone Pro Max in landscape (932px wide) and iPad in any orientation are wider than sm: but are still touch devices that trigger Safari's auto-zoom on focus. With text-base sm:text-[14px], those devices get the desktop-sized 14px and the bug returns.

Approach

Defense-in-depth at the CSS layer. The media query (hover: none) and (pointer: coarse) matches any device the browser self-reports as touch-only — regardless of viewport width — and explicitly excludes mouse-pointer environments. So:

  • iOS Safari (iPhone, iPad), iPadOS, Android phones/tablets → all form controls forced to ≥16px on focus → Safari never auto-zooms
  • Desktop macOS / Windows / Linux with a mouse → media query never matches → existing text-xs / text-sm / text-[14px] density classes apply unchanged → no visual change

Using max(16px, 1em) instead of a flat 16px preserves any intentionally larger font (e.g. heading-style inputs, .dialog-title editable headers) while still raising the floor.

This complements rather than replaces #1652 — the per-component text-base sm:text-[14px] pattern in ComposerPromptEditor.tsx and Sidebar.tsx keeps working on desktop and stays self-documenting at the component level. The new global rule is a safety net that catches everything else.

Why not the other approaches

  • maximum-scale=1 in the viewport meta (or usePreventIosInputZoom from fix: prevent iOS composer focus zoom #1562) disables pinch-to-zoom entirely while focused, hurting accessibility.
  • A lint rule on JSX <input> elements would only catch missing classes at write time and wouldn't cover the sm: breakpoint gap on iPad/landscape phones.
  • Setting text-base everywhere would change desktop UI density (12-14px is intentional for the sidebar / settings rows).

The CSS-scoped media query is the smallest, lowest-risk solution that closes both gaps.

Files

  • apps/web/src/index.css — +21 lines, no deletions, no formatting changes to surrounding code

Verification

  • Diff is purely additive (21 insertions, 0 deletions).
  • bunx prettier --check on the new block: clean.
  • (hover: none) and (pointer: coarse) is a well-supported Media Queries Level 4 feature — Safari 9+, all evergreen browsers.

Closes / refs

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

The change is presentational/preventative — it only takes effect on focus on touch devices, and the visible result is "the page does not zoom" — which is hard to capture as a screenshot. The behavior matches what #1652 already demonstrated for the composer; this PR extends the same outcome to every form control, every viewport size on touch devices.

Note

Prevent iOS Safari auto-zoom on input focus for touch devices

Adds a CSS media rule in index.css targeting touch devices (hover: none and pointer: coarse) that sets font-size: max(16px, 1em) on all input, textarea, select, and contenteditable elements. iOS Safari auto-zooms when an input's font size is below 16px; this rule ensures the minimum is always met without overriding larger sizes.

Macroscope summarized 6f857e7.

Upstream PR pingdotgg#1652 patched the chat composer and sidebar rename input by
switching from `text-[14px]` to `text-base sm:text-[14px]`, but that pattern
has two failure modes:

1. Any future input/textarea/contenteditable that lands without the
   `text-base sm:` prefix silently re-introduces the bug. There's no
   linter rule to catch it.

2. The `sm:` breakpoint is 640px, but iPad and iPhone Pro Max in
   landscape are wider than 640px while still being touch devices that
   auto-zoom on focus. The desktop-sized `sm:text-[14px]` kicks in there
   and the bug returns.

This adds a global `@media (hover: none) and (pointer: coarse)` rule that
floors all form controls to `max(16px, 1em)` — but ONLY on touch devices.
Desktop UIs keep their existing density (Tailwind `text-xs`/`text-sm`
classes apply unchanged because the touch media query never matches a
mouse-pointer environment).

Net effect: iOS Safari (any size, any orientation), iPadOS, and Android
phones/tablets never auto-zoom into our inputs. Mouse-pointer macOS,
Windows, and Linux are completely unaffected.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 1, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 934ffa5c-8bdd-4e62-8ac5-f4cbf0680471

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels May 1, 2026
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented May 1, 2026

Approvability

Verdict: Approved

CSS-only change that adds a media query to prevent iOS Safari auto-zoom on form inputs. The fix is scoped to touch devices, preserves desktop styling, and has no runtime behavior impact beyond the intended visual fix.

You can customize Macroscope's approvability policy. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant