Skip to content

Mobile: stop the conversation scrolling sideways - #71

Merged
lvwerra merged 1 commit into
mainfrom
fix/mobile-h-scroll
Aug 14, 2026
Merged

Mobile: stop the conversation scrolling sideways#71
lvwerra merged 1 commit into
mainfrom
fix/mobile-h-scroll

Conversation

@lvwerra

@lvwerra lvwerra commented Aug 13, 2026

Copy link
Copy Markdown
Member

Reported from a phone: the rendered conversation scrolls horizontally, and the scroll is not needed. Measured at a 390px viewport with playwright rather than read off the CSS — the page never scrolled; the reading column and the answer did, for two unrelated reasons.

What was actually overflowing

what how much why
.cxv-body (the reading column) 6px #49 gave the prompt band a full bleed with margin-right: -14px, matching .cxv-body's 14px padding — but the phone breakpoint narrows that padding to 8px. 14px of bleed into an 8px gutter = 6px wider than its own scroller.
.markdown.cx-md (the answer) 282px A URL and a long identifier are each one unbroken word, and one long word makes a paragraph wider than a phone pane. .markdown sets overflow-y: auto, which makes the other axis a scroller too, so the answer became draggable sideways.

Found causally, by neutralising each suspect on the live page and re-measuring, not by guessing from the stylesheet:

STOPS THE SCROLL  prompt band bleed      body Δ6→Δ0  col Δ14→Δ0  md Δ282→Δ282
no change         long tokens in prose   body Δ6→Δ6  col Δ14→Δ14  md Δ282→Δ0

The fix

  • The gutter is a variable. --cx-gutter on .cxv-body (14px, 8px on a phone) pays out both the padding and the band's bleed, so the two cannot drift apart at a breakpoint again.
  • Prose wraps. overflow-wrap: anywhere on p/li/blockquote/headings and on inline code — not on code inside pre.
  • Genuinely wide content still scrolls inside its own box, untouched: pre (796px of content at this viewport) and table (217px). No overflow-x: hidden on a parent anywhere — that hides the symptom and clips columns people need to read.

Verification

320 / 390 / 768px, each at 100% and 200% reader zoom — no horizontal scroll room on the page, on .cxv-body, on .cxv-col, or on the answer; pre and table still scroll:

PASS  iPhone SE (320) @ 100%   page room=0  .cxv-body room=0
PASS  iPhone SE (320) @ 200%   page room=0  .cxv-body room=0
PASS  iPhone 13 (390) @ 100%   page room=0  .cxv-body room=0
PASS  iPhone 13 (390) @ 200%   page room=0  .cxv-body room=0
PASS  tablet (768)    @ 100%   page room=0  .cxv-body room=0
PASS  tablet (768)    @ 200%   page room=0  .cxv-body room=0

Before → after, same 390px viewport (the long identifier now wraps onto a second line instead of running off the edge; the table still scrolls in its own box):

  • before: /tmp/hscroll-before-table.png
  • after: /tmp/hscroll-after-table.png

Unchanged elsewhere, which matters because #37 made this renderer shared: the desktop reader and the Overview card are pixel-identical before and after apart from the animated status dot in the footer — 56 differing pixels out of 1.15M, in one 8×8 box. Desktop geometry is identical too (band right edge still flush with the column's, .cxv-body 972 client / 972 scroll).

Server and web suites green.

🤖 Generated with Claude Code

Reported from a phone: the rendered conversation scrolls horizontally, and the
scroll is not needed. Two separate causes, measured at a 390px viewport rather
than read off the CSS — the page itself never scrolled, `.cxv-body` and the
answer did.

**The prompt band, 6px.** #49 gave the band a full bleed with
`margin-right: -14px` matching `.cxv-body`'s 14px padding, but the phone
breakpoint narrows that padding to 8px. The band stayed 14px wide into an 8px
gutter, so the reading column was 6px wider than its own scroller. The gutter is
now `--cx-gutter` and the bleed is `calc(-1 * var(--cx-gutter))`: one number per
breakpoint, and the band cannot drift from it again.

**Prose that could not wrap, 282px.** A URL and a long identifier are each one
unbroken word, and one long word makes a paragraph wider than a phone pane.
`.markdown` sets `overflow-y: auto`, which makes the other axis a scroller too,
so the answer itself became draggable sideways. Prose now wraps
(`overflow-wrap: anywhere` on p/li/blockquote/headings and on inline code, not
on code inside `pre`).

What deliberately still scrolls, inside its own box: `pre` (796px of content at
this viewport) and `table` (217px). Wrapping a line of code to fit would change
what it says, and `overflow-x: hidden` on a parent would clip the columns of a
table people need to read.

Verified with playwright at 320/390/768px, at 100% and 200% reader zoom: no
horizontal scroll room on the page, on `.cxv-body`, on `.cxv-col` or on the
answer, and `pre`/`table` still scroll. Desktop reader and the Overview card are
pixel-identical before and after apart from the animated status dot in the
footer (56 of 1.15M pixels, an 8×8 box). Server and web suites green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@lvwerra
lvwerra merged commit 4f34781 into main Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant