responsive
Test a web app at mobile, tablet, and desktop breakpoints. Screenshots each size, flags overflow, small touch targets, tiny text, and viewport issues. Use before shipping or after layout changes.
Files1
View on GitHubSKILL.mdresponsive/SKILL.md
GitHubResponsive Tester
Test a web app at three breakpoints and report issues.
Argument: $ARGUMENTS is either a URL (e.g., http://localhost:3000) or a project path to start a dev server for. If not provided, ask.
Breakpoints
Test at these three sizes:
- Mobile: 375 × 812 (iPhone baseline)
- Tablet: 768 × 1024 (iPad portrait)
- Desktop: 1280 × 800 (standard laptop)
Process
0. Pick a browser tool
This skill needs a way to drive a browser. Use the first one available in the session:
- Playwright MCP plugin (
browser_navigate,browser_resize,browser_take_screenshot,browser_evaluate) — the tool names below assume this. Install with/plugin install playwrightif missing. - Claude in Chrome extension (
mcp__claude-in-chrome__*) — same steps; usenavigate,resize_window,computerscreenshot, andjavascript_toolin place of the Playwright names. - Neither — fall back to the CLI for screenshots and skip the JS checks:
Then read the three PNGs and review them visually.npx playwright screenshot --viewport-size=375,812 --full-page <url> mobile.png npx playwright screenshot --viewport-size=768,1024 --full-page <url> tablet.png npx playwright screenshot --viewport-size=1280,800 --full-page <url> desktop.png
1. Get a running preview
If given a URL, open it with browser_navigate.
If given a project path, start the dev server from package.json scripts in the background, wait for it to listen, then browser_navigate to its URL.
2. Pre-flight checks (static analysis)
Before opening the browser, grep for common issues:
# Missing viewport meta
grep -L "viewport" src/app/layout.* public/index.html 2>/dev/null
# Fixed pixel widths that break on mobile
grep -rn "width: [0-9]\{3,4\}px" --include="*.css" --include="*.tsx" --include="*.jsx"
# Absolute positioning without responsive alternatives
grep -rn "position: absolute" src/ --include="*.css" --include="*.tsx"
Note anything suspicious for the browser phase.
3. Test each breakpoint
For each of mobile / tablet / desktop:
a. Resize the viewport: browser_resize to 375×812, 768×1024, or 1280×800.
b. Take a screenshot: browser_take_screenshot.
c. Check for horizontal overflow:
// Via browser_evaluate:
({
docWidth: document.documentElement.scrollWidth,
viewWidth: window.innerWidth,
overflow: document.documentElement.scrollWidth > window.innerWidth,
overflowingElements: Array.from(document.querySelectorAll('*'))
.filter(el => el.scrollWidth > window.innerWidth)
.slice(0, 5)
.map(el => ({
tag: el.tagName.toLowerCase(),
class: el.className,
width: el.scrollWidth
}))
})
d. Check touch target sizes (mobile only):
// Via browser_evaluate:
Array.from(document.querySelectorAll('button, a, input, [role="button"]'))
.map(el => {
const r = el.getBoundingClientRect();
return { tag: el.tagName, text: el.textContent?.slice(0, 30), w: r.width, h: r.height };
})
.filter(el => (el.w > 0 && el.w < 44) || (el.h > 0 && el.h < 44))
.slice(0, 10)
e. Check for tiny text:
// Via browser_evaluate:
Array.from(document.querySelectorAll('p, span, li, a, button, input'))
.map(el => {
const size = parseFloat(getComputedStyle(el).fontSize);
return { tag: el.tagName, text: el.textContent?.slice(0, 40), size };
})
.filter(el => el.size > 0 && el.size < 14)
.slice(0, 10)
4. Additional checks
Viewport meta tag (once, any breakpoint):
document.querySelector('meta[name="viewport"]')?.content || 'MISSING'
Expected: width=device-width, initial-scale=1 (or similar).
Image sizing (mobile):
Array.from(document.querySelectorAll('img'))
.map(img => ({
src: img.src.slice(0, 60),
natural: img.naturalWidth,
rendered: img.width,
oversized: img.naturalWidth > img.width * 2
}))
.filter(img => img.oversized)
.slice(0, 5)
5. Report
Format as a scored report:
## Responsive Test: [URL]
### Summary
- Mobile (375px): [Pass ✓ / Issues ⚠ / Broken ✗]
- Tablet (768px): [Pass ✓ / Issues ⚠ / Broken ✗]
- Desktop (1280px): [Pass ✓ / Issues ⚠ / Broken ✗]
### Viewport meta
✓ Correct: `width=device-width, initial-scale=1`
### Mobile (375px)
**Horizontal overflow**: ✗ Yes — page is 412px wide
- Element: `<div class="hero-grid">` renders at 420px
**Touch targets**: ⚠ 3 elements under 44px
- `<button>Subscribe</button>` — 32×32
- `<a>Read more</a>` — 28×20
- `<input type="email">` — 40×36
**Text sizes**: ⚠ 2 elements under 14px
- Footer copyright: 12px
- Badge labels: 11px
**Images**: ⚠ 1 oversized
- hero.jpg — natural 2400w, rendered 375w (load 6x data)
### Tablet (768px)
✓ No overflow
✓ All touch targets adequate
✓ Text sizes readable
### Desktop (1280px)
✓ Layout looks correct
⚠ Hero text-wrap may orphan — consider `text-wrap: balance`
### Priority fixes
1. **hero-grid overflow on mobile** — `src/components/Hero.tsx:42` — set `max-width: 100%` and use fluid sizing
2. **Subscribe button too small** — `src/components/CTA.tsx:18` — increase padding to 12px vertical minimum
3. **Oversized hero image** — use `next/image` or add responsive `srcset`
Rules
- Always test all three breakpoints — never skip one
- Take screenshots at each breakpoint (for visual verification)
- Don't flag intentional choices (e.g., sticky footer, fixed navbar)
- Lead with the issues that would break the page; fold repeats of the same defect into one item with a count
- File paths + line numbers for every actionable item
- Touch target threshold is 44×44px (Apple HIG standard)
- Text size threshold is 14px for body, can be 12px for labels/badges
- If no server is running, ask before starting one