ASK KNOX
beta
LESSON 325

Responsive and Cross-Device Visual QA

A page perfect at 1440px can be catastrophic at 375px — systematic workflow for testing at multiple breakpoints and writing viewport-aware findings Claude Code can act on.

10 min read·Unchaining UI — Visual Testing with Claude

Introduction

Claude Code writes responsive CSS. It knows about Tailwind's sm:, md:, and lg: prefixes. It understands flexbox and grid. And yet, without visual feedback, it will produce responsive code that breaks in ways you only discover when you resize the browser.

This is not a Claude Code limitation — it is a fundamental property of visual work. Responsive behavior is emergent. A component that is perfectly spec'd at one breakpoint can fail at another in ways that are impossible to predict from reading the code. You have to see it.

This lesson gives you a systematic workflow for cross-device visual QA: which breakpoints to test, how to capture screenshots at each, how to identify responsive-specific failure patterns, and how to write findings that Claude Code can act on at the right breakpoint.

Core Concept: The Breakpoint Checklist

Test at a minimum of three widths. These three cover the dominant device categories:

BreakpointWidthDeviceWhy it matters
Mobile375pxiPhone SE / standard phoneSmallest common viewport. Exposes the most failures.
Tablet768pxiPad portraitFlex layouts often partially collapse here. Nav menus are in-between states.
Desktop1440pxyour laptop / standard monitorYour "default" view. Usually where components look best.

If your product has significant traffic at other sizes — 1280px (13" laptop), 390px (iPhone 15), 1920px (large monitor) — add those as secondary tests. But the three above are non-negotiable.

The order matters: always test mobile first. Responsive failures compound upward. A broken mobile layout often reveals assumptions in the CSS structure that will cause subtler failures at larger sizes too.


Practical Application: Chrome DevTools Device Mode

Chrome DevTools Device Mode gives you consistent, reproducible viewport screenshots without needing a physical device.

Opening Device Mode:

  1. Open Chrome DevTools (F12 or Cmd+Option+I on Mac)
  2. Click the device toggle icon in the top-left of DevTools (or Ctrl+Shift+M / Cmd+Shift+M)
  3. A device toolbar appears above your page

Setting exact viewport widths: In the top bar, you can enter exact pixel dimensions. Type 375 for the width to simulate an iPhone SE. The page reflows to that width.

Capturing screenshots in Device Mode: Click the three-dot menu in the Device toolbar → "Capture screenshot." This saves a screenshot at exactly the displayed viewport width, including any DPR (device pixel ratio) scaling. This is more reliable than resizing your browser window manually.

The DPR note: On Retina displays, 375px at 2x DPR gives you a 750px physical screenshot. When you are comparing before/after screenshots, make sure you are comparing at the same DPR setting. Use "Responsive" mode and set DPR to 1 if you want 1:1 pixel screenshots for easier comparison.

Preset devices: Chrome has presets for common devices (iPhone 14, iPad, Galaxy S23). These set both viewport width and DPR. They are useful for a final verification pass but less useful for systematic QA where you want control over the exact width.


Common Responsive Failures Claude Code Produces

These are the patterns that appear most often when you inspect Claude Code output across breakpoints. Knowing them ahead of time means your inspection is faster — you know where to look.

1. Text Overflow on Mobile

Long labels, headings, and stat values that fit at 1440px will overflow or break oddly at 375px. The component has no overflow-hidden or truncate class, and the text pushes outside its container.

What it looks like: Text extends beyond the card edge, or the card itself grows wider than the viewport, causing horizontal scroll.

Fix signal to give Claude Code: "At 375px the metric value overflows the card — add overflow-hidden to the card container or truncate to the value element."

2. Images Not Scaling

Images set to fixed pixel widths do not shrink on mobile. A 400px wide image in a 375px viewport will either overflow or force horizontal scroll.

Fix signal: "Image at 375px is overflowing the container — change from w-[400px] to w-full max-w-[400px]."

3. Flex Layouts Collapsing Incorrectly

A flex row that should stack vertically on mobile may stay horizontal because the component uses flex without flex-col and sm:flex-row, or it stacks when it should not because of an over-applied flex-wrap.

Fix signal: "At 375px the two stat cards are side-by-side but too narrow to read — they should stack vertically. Change to flex-col sm:flex-row."

4. Padding Crowding on Mobile

Desktop padding that looks generous at 1440px becomes claustrophobic at 375px, or elements become unclickable because they are too close together. Claude Code often uses the same padding value across all breakpoints.

Fix signal: "At 375px the card internal padding is too tight — reduce from p-6 to p-4 sm:p-6."

5. Navigation Not Collapsing

A desktop nav with five links will not fit at 375px. Claude Code may write the nav as a visible row at all widths, with no hamburger menu or collapse behavior.

Fix signal: "At 375px the nav links are visible in a row and overflowing — they should be hidden, replaced by a hamburger icon. Implement a useState toggle to show/hide the mobile menu."

6. Grid Breaking Into Wrong Column Count

A grid-cols-3 grid that looks correct at 1440px will render three tiny columns at 375px. The mobile breakpoint should use grid-cols-1 with sm:grid-cols-2 and lg:grid-cols-3.


Writing Viewport-Aware Findings

This is the critical skill for responsive QA. If you write "the layout is broken on mobile," Claude Code may apply a fix that changes the desktop layout as a side effect, or it may apply the fix in the base CSS instead of inside a media query.

Always include:

  1. The exact breakpoint where the issue occurs
  2. Whether it is a mobile-only issue or a cross-breakpoint issue
  3. The Tailwind prefix or media query scope where the fix belongs

Good finding:

At 375px (mobile only), the footer button row is overflowing the card edge.
The buttons should stack vertically on mobile.
Fix: Add flex-col sm:flex-row to the button container.
Do not change the desktop layout.

Bad finding:

The buttons look broken.

Good finding:

At 768px (tablet), the sidebar is partially visible but overlapping the main content.
At 1440px it is correct.
Fix: Add hidden md:block to the sidebar so it only renders at md and above.
On mobile/tablet, do not render the sidebar at all.

The difference between these two findings is not politeness — it is where the fix physically lands in the code. A scoped finding keeps the edit inside the right responsive prefix; a vague one sends it into the base CSS, where it silently overwrites a breakpoint that was already correct.

A complete viewport-aware audit format:

Responsive audit — [Component Name]

Tested at: 375px, 768px, 1440px

DESKTOP (1440px) — No issues.

TABLET (768px):
1. Sidebar overlaps main content. Should not render at this breakpoint.
   Fix: sidebar wrapper should be hidden md:block (or hidden lg:block if sidebar
   is desktop-only).

MOBILE (375px):
2. Stat value text "Average Customer Acquisition Cost" overflows card.
   Fix: Add truncate or text-ellipsis overflow-hidden to the value element.
3. Footer buttons are side-by-side, too narrow for touch. Should stack.
   Fix: footer buttons: flex-col sm:flex-row gap-3.
4. Card padding p-6 is too tight at this width. Reduce to p-4 sm:p-6.

Fix only these items. Do not change 1440px layout.

The Mobile-First Verification Order

After Claude Code applies responsive fixes:

  1. Verify mobile (375px) first. This is where most fixes were applied. Confirm each finding is resolved.

  2. Check tablet (768px). Any tablet-specific fixes resolved? No regressions from mobile fixes?

  3. Check desktop (1440px). This is where regressions are most likely to appear. A flex-col fix on mobile should only apply below sm: — if Claude Code forgot the sm:flex-row counterpart, the desktop layout breaks.

  4. Check one intermediate width (1024px or 1280px). This catches the "in-between" state where breakpoints collide unexpectedly.

If you find a regression at desktop introduced by a mobile fix, feed it back immediately. Do not continue the responsive audit while there is a desktop regression open.


Automating the Screenshot Matrix

For teams or projects with many pages, capturing screenshots manually at three breakpoints per page becomes tedious. You can automate it with a simple shell script using Chrome headless.

#!/bin/bash
# capture-responsive.sh — screenshot a URL at 3 breakpoints
# Usage: ./capture-responsive.sh http://localhost:3000/dashboard

URL=$1
SLUG=$(echo "$URL" | sed 's|http://||' | sed 's|/|-|g' | sed 's|:||g')
OUTDIR="screenshots/responsive"
mkdir -p "$OUTDIR"

for WIDTH in 375 768 1440; do
  echo "Capturing ${WIDTH}px..."
  /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
    --headless \
    --disable-gpu \
    --window-size="${WIDTH},900" \
    --screenshot="${OUTDIR}/${SLUG}-${WIDTH}.png" \
    "$URL"
done

echo "Done. Saved to ${OUTDIR}/"

This produces three files:

  • localhost-3000-dashboard-375.png
  • localhost-3000-dashboard-768.png
  • localhost-3000-dashboard-1440.png

Upload all three to claude.ai (or the claude.ai Projects interface) and ask for a responsive audit in a single message. You get three viewports analyzed in one pass.

Playwright is even better for this. In the “Visual QA in CI” lesson you will set up a full Playwright visual regression suite. But the bash approach above is useful for quick one-off checks during development before you have Playwright wired up.


Example Walkthrough: Tailwind Responsive Audit

Here is a real responsive issue trace. The component is a two-column feature grid.

Claude Code output:

<div className="grid grid-cols-2 gap-8 p-8">
  {features.map(f => (
    <FeatureCard key={f.id} {...f} />
  ))}
</div>

1440px: Looks correct. Two columns, good spacing.

768px: Two columns still visible but cramped. Cards are ~320px wide each with gap-8 (32px). Acceptable but tight.

375px: Two columns are ~155px each. Text is unreadable. Icons are squished. Classic responsive failure.

Audit finding:

At 375px the feature grid renders two columns at ~155px each — text is
unreadable and icons are squished. The grid should stack to a single
column on mobile.

Fix: Change grid-cols-2 to grid-cols-1 sm:grid-cols-2.

At 768px the two-column layout is acceptable. Do not change it.
Do not change the 1440px layout.

After fix:

<div className="grid grid-cols-1 sm:grid-cols-2 gap-8 p-8">

Verification: 375px shows single column, readable. 768px shows two columns, unchanged. 1440px unchanged.

One finding, one fix, verified at all three breakpoints.


Common Mistakes

Testing only at your current screen resolution. Your 1440px or 1920px monitor is the least likely place Claude Code output breaks. Always resize to 375px. Always.

Writing findings without a breakpoint. "The sidebar is broken" gives Claude Code no location context. It may apply a global fix that breaks other breakpoints.

Fixing mobile after desktop. Fix mobile first. Desktop is more forgiving. Mobile failures are usually structural; desktop failures are usually visual polish after the structure is right.

Not verifying desktop after a mobile fix. Every flex-col needs a sm:flex-row counterpart. Every hidden needs a sm:block counterpart. Check desktop after every mobile fix.


Summary

Responsive QA is not a separate pass you do at the end — it is part of every visual QA loop. Every component needs to be inspected at 375px, 768px, and 1440px minimum. Claude Code writes responsive code blindly, and the failures are predictable: text overflow, collapsed flex rows, missing nav toggles, and padding crowding.

The key skill is writing viewport-aware findings: always specify the breakpoint, always specify which other breakpoints should not change, and always give Claude Code the exact Tailwind prefix or media query scope where the fix belongs.


What's Next

The next lesson goes further: instead of you taking screenshots and handing them to Claude Code, you set up the Computer-Use MCP so Claude can take its own screenshots, navigate the browser, and run visual QA loops autonomously. This is the shift from manual handoff to automated in-loop visual inspection.


Exercise

Take the page you built in the previous lesson (nav, sidebar, content area with two stat cards, footer).

  1. Open it in Chrome DevTools Device Mode
  2. Capture screenshots at 375px, 768px, and 1440px
  3. Upload all three to claude.ai in a single message with the prompt: "Identify all responsive visual issues in these three screenshots. Organize your findings by breakpoint."
  4. Take Claude's audit output and format it into a viewport-aware audit report using the format from this lesson
  5. Feed the structured audit to Claude Code with "Fix only these items. Do not change layouts at unaffected breakpoints."
  6. Re-capture screenshots at all three widths after fixes
  7. Compare before/after at each breakpoint

Note how many issues were mobile-only vs. cross-breakpoint. Note any desktop regressions from mobile fixes. Document them in your audit log with timestamps.