My markdown code viewer worked perfectly on desktop. On tablet, horizontal scroll. On mobile, buttons overflowing the viewport. The classic. Except this time, instead of spending 2 hours in DevTools manually resizing, I let Claude Code run the loop: screenshot → diagnose → fix → retest. 10 minutes, zero overflow across 10 resolutions. Here's the workflow.
The problem — the overflow you don't see
The scenario is always the same. You code on a 1920px screen.
Everything lines up. The layout breathes. You ship. Then someone opens
it on an iPad and a horizontal scrollbar appears. On an iPhone SE, a button
bleeds past the right edge. The pre blocks expand beyond the viewport
and drag the entire page with them.
The real issue isn't the CSS. It's the feedback loop. On desktop you never see the overflow — because there's nothing to overflow. Detecting it requires resizing, which requires switching tools, which requires discipline you don't have at 11 PM when you're shipping a feature.
There's a one-liner that exposes the problem programmatically:
document.querySelectorAll('*').filter(el =>
el.scrollWidth > el.clientWidth
).map(el => el.tagName + ' ' + el.className)
Run this in the DevTools console at any viewport width and you get the exact list of offending elements. The problem: you have to remember to run it, at the right width, for every breakpoint. Nobody does that manually.
The tool — Playwright MCP in Claude Code
Playwright MCP exposes four tools that are all you need for this kind of work:
browser_navigate— load a URL in the headless browserbrowser_resize— set the viewport to an exact width/heightbrowser_take_screenshot— capture the current state as an imagebrowser_evaluate— run arbitrary JavaScript in the page context
The key tool is browser_evaluate. It lets Claude Code run the
overflow detection one-liner directly in the page, at any resolution, and get
back the result as structured data. No screenshots needed to know if
there's a problem — only to understand what it looks like.
The detection script:
Array.from(document.querySelectorAll('*'))
.filter(el => el.scrollWidth > el.clientWidth)
.map(el => ({
tag: el.tagName,
class: el.className,
scrollWidth: el.scrollWidth,
clientWidth: el.clientWidth,
overflow: el.scrollWidth - el.clientWidth
}))
Returns an empty array? No overflow. Returns elements? Claude has the tag, the class, and the exact number of pixels overflowing. Enough to go straight to the fix.
The loop workflow
The workflow runs against 8 target resolutions, chosen to cover the main device categories:
| Resolution | Target |
|---|---|
| 375px | iPhone SE — narrowest mainstream screen |
| 390px | iPhone 14/15 — current iOS baseline |
| 412px | Android mid-range (Pixel, Samsung A-series) |
| 480px | Large phone / small phone landscape |
| 768px | iPad portrait |
| 900px | iPad landscape / small laptop |
| 1280px | Standard laptop |
| 1920px | Desktop — the baseline nobody tests against |
For each resolution, the loop is:
- Resize —
browser_resizeto the target width - Navigate —
browser_navigateto reload the page - Evaluate — run the overflow detection script
- Screenshot — only if overflow is detected (saves time)
- Fix — edit the CSS directly in the source file
- Reload and retest — confirm the fix eliminated the overflow
The loop doesn't move to the next resolution until the current one returns zero overflow. No approximation, no "probably fine on mobile".
The prompt that does everything
One prompt to Claude Code and it runs the entire loop autonomously:
I need you to do a full responsive overflow audit on my blog view page.
Target URL: http://localhost:8000/blog/claude-md/view.php?ctx=mobile-css-redesign
Test these resolutions in order: 375, 390, 412, 480, 768, 900, 1280, 1920px.
For each resolution:
1. browser_resize to the target width (height: 900)
2. browser_navigate to reload the page
3. browser_evaluate this script:
Array.from(document.querySelectorAll('*'))
.filter(el => el.scrollWidth > el.clientWidth)
.map(el => ({ tag: el.tagName, class: el.className,
overflow: el.scrollWidth - el.clientWidth }))
4. If the result is non-empty: browser_take_screenshot, then identify the
CSS rule causing the overflow and fix it in the source file directly.
5. After each fix: reload and re-evaluate to confirm zero overflow.
6. Move to next resolution only when current one is clean.
Report: for each resolution, list elements that overflowed and the fix applied.
Final summary: total fixes made, time per resolution.
That's the entire prompt. Claude Code reads it, runs Playwright MCP, edits the CSS files when needed, retests, and gives you a summary at the end. You watch it work.
Concrete results
On my view.php — the markdown code viewer for the CLAUDE.md catalogue —
the audit found 6 overflow issues across 4 resolutions. Before: 2 hours of manual
DevTools resizing. After the automated loop: 10 minutes, including Claude Code time
to identify and fix each issue.
The issues found, in order of frequency:
-
Pre blocks expanding beyond viewport (375px, 390px, 412px) —
preelements with nowhite-space: pre-wraporword-break: break-word. The code was wider than the screen. -
Button row overflowing on mobile (375px, 390px) —
a flex row of three buttons with no
flex-wrap: wrap. At 375px, the third button disappeared off-screen. -
Inline code spilling (480px) —
codeelements inside paragraphs withwhite-space: nowrapinherited from a parent rule. A single long identifier broke the layout. -
Sidebar min-width too wide (768px) —
a
min-width: 320pxon a panel that should collapse towidth: 100%on tablet.
Each fix was applied directly to blog.css or view.php's
inline styles, retested immediately, and confirmed clean before moving on.
The manual alternative: open DevTools, drag the viewport handle, squint at the scrollbar, right-click → Inspect, trace which rule is overriding what, fix, reload, repeat. For 8 resolutions and 6 issues, that's 2+ hours minimum.
CSS rules to remember
The fixes applied in this session reduce to five CSS patterns that cover 90% of real-world overflow cases:
1. overflow-x: hidden on html and body.
The base safety net. Doesn't fix the root cause, but contains the damage.
Warning: breaks position: sticky if applied to the wrong element.
html, body {
overflow-x: hidden;
max-width: 100%;
}
2. pre-wrap and word-break on code blocks.
pre elements preserve whitespace, which means they expand
horizontally forever if you let them. These two rules wrap them instead.
pre {
white-space: pre-wrap;
word-break: break-word;
overflow-x: auto; /* fallback for very long unbreakable tokens */
}
3. flex-wrap: wrap on button rows. Any flex row that contains multiple buttons needs this on mobile. Fixed widths in a flex container are a recipe for overflow.
.button-row {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
4. max-width: 100% on images and media. An image wider than its container will push the layout. This should be in every project's reset.
img, video, svg, canvas {
max-width: 100%;
height: auto;
}
5. text-wrap: balance on headings. Not an overflow fix — a readability one. Prevents awkward line breaks on narrow viewports where a long heading wraps with one word on the last line.
h1, h2, h3 {
text-wrap: balance;
}
For a complete mobile CSS reference — touch targets, iOS zoom prevention, safe-area-inset, form inputs — see the article on mobile CSS best practices.
Conclusion
Responsive isn't a CSS problem. It's a feedback loop problem. The CSS rules that fix overflow are not complex — five patterns cover most cases. The problem is that you don't see the overflow until you're at the right viewport, and getting to the right viewport, for every breakpoint, is friction enough that it doesn't happen consistently.
The Playwright MCP loop eliminates that friction. Claude Code runs the detection script at every resolution, identifies the element, reads the source, applies the fix, retests. The loop is mechanical — exactly the kind of work that should be automated.
The workflow works on any page served locally. The prompt is generic enough to reuse as-is on any project. The only thing that changes is the URL. For the full context on how to integrate this into a CLAUDE.md workflow, see the article on specialized CLAUDE.md for mobile redesign.