| name | responsive-design |
| description | Make UIs responsive across all devices and verify responsiveness using Playwright. Includes scrollbar testing, breakpoint verification, and layout validation. Use when implementing new features, fixing layout issues, or ensuring mobile compatibility. |
Responsive Design & Verification Skill
Purpose
Ensure all UI features are fully responsive and work correctly across all device sizes, from mobile to desktop. This skill provides:
- Responsive design patterns using Tailwind CSS
- Automated verification using Playwright MCP resize capability
- Scrollbar and overflow testing
- Guidelines for providing sufficient data to trigger scrollbars
Standard Breakpoints
Follow Tailwind's default breakpoints:
| Breakpoint | Min Width | Device Type | Use Case |
|---|
xs (default) | 0px | Mobile | Base styles, mobile-first |
sm: | 640px | Large mobile | Larger phones in landscape |
md: | 768px | Tablet | iPads, tablets |
lg: | 1024px | Laptop | Laptops, small desktops |
xl: | 1280px | Desktop | Standard desktop |
2xl: | 1536px | Large Desktop | Large monitors |
Testing Sizes
Use these specific dimensions for Playwright testing:
const testSizes = [
{ width: 375, height: 667, name: 'Mobile (iPhone SE)' },
{ width: 768, height: 1024, name: 'Tablet (iPad)' },
{ width: 1280, height: 720, name: 'Desktop (HD)' },
{ width: 1920, height: 1080, name: 'Desktop (Full HD)' },
];
Or use device presets:
const devicePresets = [
'iPhone 13',
'iPad Pro 11',
'Desktop Chrome'
];
Responsive Design Patterns
1. Navigation
Mobile (< 768px):
- Hamburger menu icon
- Collapsed navigation drawer
- Single-column layout
Desktop (≥ 768px):
- Full horizontal navigation bar
- All menu items visible
- Logo and nav items side-by-side
<nav className="flex items-center justify-between p-4">
{}
<button className="md:hidden">
<HamburgerIcon />
</button>
{}
<div className="hidden md:flex space-x-4">
<NavLink href="/dashboard">Dashboard</NavLink>
<NavLink href="/jobs">Jobs</NavLink>
<NavLink href="/sites">Sites</NavLink>
</div>
</nav>
2. Data Tables
Mobile:
- Stack rows as cards
- Show key fields only
- Horizontal scroll for full table (if needed)
Desktop:
- Traditional table layout
- All columns visible
- Sortable headers
{}
<div className="md:hidden space-y-4">
{items.map(item => (
<Card key={item.id}>
<div className="flex justify-between">
<span className="font-bold">{item.name}</span>
<Badge>{item.status}</Badge>
</div>
<div className="text-sm text-gray-600">{item.date}</div>
</Card>
))}
</div>
{}
<div className="hidden md:block overflow-x-auto">
<table className="min-w-full">
<thead>
<tr>
<th>Name</th>
<th>Status</th>
<th>Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{items.map(item => (
<tr key={item.id}>
<td>{item.name}</td>
<td><Badge>{item.status}</Badge></td>
<td>{item.date}</td>
<td><Actions item={item} /></td>
</tr>
))}
</tbody>
</table>
</div>
3. Forms
Mobile:
- Single column layout
- Full-width inputs
- Stacked label above input
- Large touch targets (min 44x44px)
Desktop:
- Can use grid layout (2+ columns for simple fields)
- Inline labels for short fields
- More compact spacing
<form className="space-y-4">
{}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium mb-1">First Name</label>
<input className="w-full px-3 py-2 border rounded" />
</div>
<div>
<label className="block text-sm font-medium mb-1">Last Name</label>
<input className="w-full px-3 py-2 border rounded" />
</div>
</div>
{}
<div>
<label className="block text-sm font-medium mb-1">Email</label>
<input className="w-full px-3 py-2 border rounded" />
</div>
{}
<button className="w-full md:w-auto px-6 py-2 bg-blue-600 text-white rounded">
Submit
</button>
</form>
4. Layout Containers
Use appropriate padding and max-widths:
{}
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
{}
</div>
{}
<div className="max-w-7xl mx-auto">
{}
</div>
{}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{}
</div>
5. Typography
{}
<h1 className="text-2xl md:text-3xl lg:text-4xl font-bold">
Page Title
</h1>
<p className="text-sm md:text-base lg:text-lg">
Body text that scales appropriately.
</p>
Scrollbars & Overflow Testing
Ensuring Scrollbars Appear
Always provide sufficient mock data to trigger scrollbars during testing:
- Lists/Tables: Minimum 15-20 items (ensures vertical scroll on most screens)
- Long text content: Use realistic paragraph lengths (100+ words)
- Horizontal content: Test with wide tables (8+ columns)
- Nested scrolling: Test both page-level and container-level scrolls
Overflow Patterns
Vertical Scroll (Full Page):
<div className="min-h-screen">
{}
{items.map(item => <ItemCard key={item.id} item={item} />)}
</div>
Container Scroll (Fixed Height):
<div className="h-96 overflow-y-auto border rounded">
{}
{items.map(item => <ItemCard key={item.id} item={item} />)}
</div>
Horizontal Scroll (Tables):
<div className="overflow-x-auto">
<table className="min-w-full">
{/* Wide table that scrolls horizontally on small screens */}
</table>
</div>
Scroll with Sticky Headers:
<div className="h-96 overflow-y-auto">
<table>
<thead className="sticky top-0 bg-white">
<tr>{/* Headers stay visible while scrolling */}</tr>
</thead>
<tbody>
{/* Scrollable rows */}
</tbody>
</table>
</div>
Playwright Verification Workflow
Use Playwright MCP tools to verify responsive behavior at each breakpoint.
1. Navigate to Feature
await mcp_playwright_navigate({
url: 'http://localhost:5173/jobs',
width: 1280,
height: 720
});
2. Test Each Breakpoint
const breakpoints = [
{ width: 375, height: 667, name: 'Mobile' },
{ width: 768, height: 1024, name: 'Tablet' },
{ width: 1280, height: 720, name: 'Desktop' },
];
for (const breakpoint of breakpoints) {
await mcp_playwright_resize({
width: breakpoint.width,
height: breakpoint.height
});
await mcp_playwright_screenshot({
name: `feature-${breakpoint.name.toLowerCase()}`,
savePng: true
});
await mcp_playwright_get_visible_text();
}
3. Verify Scrollbars
Check if content is scrollable:
await mcp_playwright_evaluate({
script: `
const hasVerticalScroll = document.documentElement.scrollHeight > window.innerHeight;
const hasHorizontalScroll = document.documentElement.scrollWidth > window.innerWidth;
return {
hasVerticalScroll,
hasHorizontalScroll,
scrollHeight: document.documentElement.scrollHeight,
clientHeight: window.innerHeight,
scrollWidth: document.documentElement.scrollWidth,
clientWidth: window.innerWidth
};
`
});
Test scrolling behavior:
await mcp_playwright_evaluate({
script: 'window.scrollTo(0, document.documentElement.scrollHeight);'
});
await mcp_playwright_screenshot({
name: 'scrolled-to-bottom',
savePng: true
});
await mcp_playwright_evaluate({
script: 'window.scrollTo(0, 0);'
});
Test container scrolling:
await mcp_playwright_evaluate({
script: `
const container = document.querySelector('.scrollable-container');
if (container) {
container.scrollTop = container.scrollHeight;
return { scrolled: true, scrollHeight: container.scrollHeight };
}
return { scrolled: false };
`
});
4. Check for Common Issues
await mcp_playwright_evaluate({
script: `
const bodyWidth = document.body.scrollWidth;
const windowWidth = window.innerWidth;
const hasOverflow = bodyWidth > windowWidth;
// Find elements causing overflow
const overflowElements = Array.from(document.querySelectorAll('*'))
.filter(el => el.scrollWidth > windowWidth)
.map(el => ({
tag: el.tagName,
class: el.className,
width: el.scrollWidth
}));
return { hasOverflow, bodyWidth, windowWidth, overflowElements };
`
});
Responsive Design Checklist
For each new feature, verify:
Layout
Navigation
Forms
Tables/Lists
Typography
Scrollbars
Images/Media
Touch Interactions
Common Mistakes to Avoid
- Desktop-first thinking: Always start with mobile layout, enhance for desktop
- Fixed widths: Use
w-full, max-w-*, avoid w-[500px] except for specific cases
- Too many breakpoints: Stick to 2-3 key breakpoints per feature
- Inconsistent navigation: Nav pattern should be the same across all pages
- Insufficient test data: Always provide 15-20+ items to test scrolling
- Ignoring horizontal overflow: Always check for unintentional horizontal scroll
- Tiny touch targets: Mobile buttons must be large enough (44x44px minimum)
- Hidden content on mobile: Ensure all critical content accessible on small screens
Integration with Other Skills
- implement-feature: Call this skill after initial implementation to verify responsiveness
- write-e2e-test: Include responsive tests in E2E test suites
- generate-sample-data: Ensure sample generators create enough data (15-20+ items)
Example: Complete Responsive Verification
await mcp_playwright_navigate({
url: 'http://localhost:5173/jobs',
width: 1280,
height: 720
});
const devices = ['iPhone 13', 'iPad Pro 11', 'Desktop Chrome'];
for (const device of devices) {
await mcp_playwright_resize({ device });
await mcp_playwright_screenshot({
name: `jobs-${device.toLowerCase().replace(/\s+/g, '-')}`,
savePng: true
});
const text = await mcp_playwright_get_visible_text();
console.log(`${device} visible content:`, text);
}
await mcp_playwright_resize({ width: 1280, height: 720 });
const scrollInfo = await mcp_playwright_evaluate({
script: `
return {
hasScroll: document.documentElement.scrollHeight > window.innerHeight,
scrollHeight: document.documentElement.scrollHeight,
viewportHeight: window.innerHeight,
itemCount: document.querySelectorAll('.job-card').length
};
`
});
console.log('Scroll info:', scrollInfo);
await mcp_playwright_evaluate({
script: 'window.scrollTo(0, document.documentElement.scrollHeight);'
});
await mcp_playwright_screenshot({
name: 'jobs-scrolled-bottom',
savePng: true
});
const overflowCheck = await mcp_playwright_evaluate({
script: `
return {
hasHorizontalOverflow: document.body.scrollWidth > window.innerWidth,
bodyWidth: document.body.scrollWidth,
windowWidth: window.innerWidth
};
`
});
if (overflowCheck.hasHorizontalOverflow) {
console.error('⚠️ Horizontal overflow detected!', overflowCheck);
}
Success Criteria
A feature is considered responsive when:
- ✅ Works on mobile (375px), tablet (768px), and desktop (1280px+)
- ✅ No horizontal overflow at any breakpoint
- ✅ All content accessible without horizontal scrolling (except intentional table scroll)
- ✅ Vertical scrollbars appear with sufficient data (15-20+ items)
- ✅ Navigation adapts appropriately (hamburger on mobile, full nav on desktop)
- ✅ Forms are usable on all screen sizes
- ✅ Touch targets meet minimum size requirements (44x44px)
- ✅ Screenshots verify layout at each breakpoint
- ✅ Playwright tests confirm scrolling behavior
Resources