
responsive-layout
by toddmoy
SKILL.md
name: "responsive layout" description: "Responsive layout considerations using CSS and Javascript. When Claude needs to build responsive, fluid layouts." license: Proprietary
Responsive Layout Skill
You are a specialized responsive design expert focused on creating fluid, mobile-first layouts using Tailwind CSS, CSS Grid, Flexbox, and React patterns.
Available Tools in This Repo
1. Tailwind CSS
Full Tailwind CSS with default breakpoints and utilities. Configured with:
- Dark mode support via
dark:prefix - Typography plugin (
@tailwindcss/typography) - Custom CSS variables for theming
- Default breakpoints:
sm(640px),md(768px),lg(1024px),xl(1280px),2xl(1536px)
2. React Resizable Panels
Available via react-resizable-panels (shadcn Resizable component):
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@/components/ui/resizable'
3. Utility Hooks Available
From usehooks-ts and @uidotdev/usehooks:
useMediaQuery(query)- Match media queriesuseWindowSize()- Get window dimensionsuseDebounce(value, delay)- Debounce values
4. Helper Classes
.center-content- Flexbox centering utility (defined insrc/index.css)
Core Principles
- Mobile-first approach - Start with mobile styles, add breakpoint modifiers for larger screens
- Use semantic breakpoints - Think in terms of content, not devices
- Leverage Flexbox and Grid - Modern CSS layout tools
- Container queries when appropriate - For component-level responsiveness
- Test at all breakpoints - Ensure no layout breaks between defined breakpoints
- Consider touch targets - Minimum 44x44px for interactive elements on mobile
- Optimize for readability - Line length, spacing, and hierarchy adapt to screen size
Tailwind Breakpoints
Default: 0px (mobile-first)
sm: 640px (large phones, small tablets)
md: 768px (tablets)
lg: 1024px (laptops, small desktops)
xl: 1280px (desktops)
2xl: 1536px (large desktops)
Usage: Apply base styles without prefix, then add breakpoint prefixes:
<div className="text-sm md:text-base lg:text-lg">
Responsive text
</div>
Common Responsive Patterns
1. Responsive Grid Layouts
Auto-fit columns (responsive without breakpoints):
<div className="grid grid-cols-[repeat(auto-fit,minmax(250px,1fr))] gap-4">
{items.map(item => <Card key={item.id} {...item} />)}
</div>
Breakpoint-based columns:
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
{items.map(item => <Card key={item.id} {...item} />)}
</div>
Asymmetric layout (sidebar + content):
<div className="grid grid-cols-1 lg:grid-cols-[250px_1fr] gap-6">
<aside className="order-2 lg:order-1">Sidebar</aside>
<main className="order-1 lg:order-2">Main content</main>
</div>
Dashboard grid:
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4">
<div className="md:col-span-2">Large widget</div>
<div>Small widget</div>
<div>Small widget</div>
<div className="xl:col-span-2">Medium widget</div>
<div className="xl:col-span-2">Medium widget</div>
</div>
2. Responsive Flexbox Layouts
Horizontal to vertical stack:
<div className="flex flex-col md:flex-row gap-4 md:gap-6">
<div className="flex-1">Left</div>
<div className="flex-1">Right</div>
</div>
Wrapping cards:
<div className="flex flex-wrap gap-4">
{items.map(item => (
<div key={item.id} className="flex-1 min-w-[280px] max-w-[400px]">
<Card {...item} />
</div>
))}
</div>
Responsive navigation:
<nav className="flex flex-col md:flex-row items-start md:items-center gap-2 md:gap-6">
<a href="/" className="text-lg font-bold">Logo</a>
<div className="flex flex-col md:flex-row gap-2 md:gap-4">
<a href="/about">About</a>
<a href="/contact">Contact</a>
</div>
</nav>
3. Container Sizing
Responsive containers:
<div className="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
Content constrained to max width with responsive padding
</div>
Breakpoint-specific max widths:
<div className="w-full max-w-sm md:max-w-2xl lg:max-w-4xl mx-auto">
Container grows at breakpoints
</div>
Full bleed on mobile, contained on desktop:
<div className="w-full lg:max-w-5xl lg:mx-auto">
<div className="px-0 lg:px-8">
Content
</div>
</div>
4. Responsive Typography
Fluid text sizing:
<h1 className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold">
Heading
</h1>
<p className="text-sm sm:text-base lg:text-lg leading-relaxed">
Body text
</p>
Responsive line length:
<div className="max-w-prose mx-auto text-base md:text-lg">
Optimal reading width (65-75 characters)
</div>
5. Show/Hide Elements
Hide on mobile, show on desktop:
<div className="hidden md:block">
Desktop only content
</div>
Show on mobile, hide on desktop:
<div className="block md:hidden">
Mobile only content
</div>
Different content at breakpoints:
<>
<MobileMenu className="md:hidden" />
<DesktopMenu className="hidden md:flex" />
</>
6. Responsive Spacing
Adaptive padding/margin:
<div className="p-4 md:p-6 lg:p-8">
Padding increases with screen size
</div>
<div className="space-y-4 md:space-y-6 lg:space-y-8">
Vertical spacing increases
</div>
Responsive gaps:
<div className="flex gap-2 sm:gap-4 md:gap-6 lg:gap-8">
Flexible gap spacing
</div>
7. Aspect Ratios
Responsive aspect ratio:
<div className="aspect-square sm:aspect-video lg:aspect-[21/9]">
<img src="..." className="w-full h-full object-cover" alt="..." />
</div>
Fixed aspect with responsive sizing:
<div className="w-full max-w-xs sm:max-w-md lg:max-w-lg aspect-video">
<video className="w-full h-full" />
</div>
React Patterns for Responsive Design
1. Using useMediaQuery Hook
import { useMediaQuery } from 'usehooks-ts'
const MyComponent = () => {
const isMobile = useMediaQuery('(max-width: 768px)')
const isDesktop = useMediaQuery('(min-width: 1024px)')
return (
<div>
{isMobile ? <MobileView /> : <DesktopView />}
</div>
)
}
2. Using useWindowSize Hook
import { useWindowSize } from 'usehooks-ts'
const MyComponent = () => {
const { width, height } = useWindowSize()
return (
<div>
Viewport: {width} x {height}
{width < 768 && <MobileNav />}
</div>
)
}
3. Responsive Component Variants
interface CardProps {
variant?: 'mobile' | 'desktop' | 'responsive'
}
const Card = ({ variant = 'responsive' }: CardProps) => {
const isMobile = useMediaQuery('(max-width: 768px)')
const getVariant = () => {
if (variant === 'responsive') {
return isMobile ? 'mobile' : 'desktop'
}
return variant
}
const variantStyles = {
mobile: 'flex-col p-4',
desktop: 'flex-row p-6'
}
return (
<div className={cn('flex', variantStyles[getVariant()])}>
Content
</div>
)
}
4. Render Props Pattern
const Responsive = ({
mobile,
tablet,
desktop
}: {
mobile: ReactNode
tablet?: ReactNode
desktop: ReactNode
}) => {
const isMobile = useMediaQuery('(max-width: 767px)')
const isTablet = useMediaQuery('(min-width: 768px) and (max-width: 1023px)')
if (isMobile) return mobile
if (isTablet && tablet) return tablet
return desktop
}
// Usage
<Responsive
mobile={<MobileLayout />}
tablet={<TabletLayout />}
desktop={<DesktopLayout />}
/>
Resizable Panels
For split views and adjustable layouts:
import {
ResizablePanelGroup,
ResizablePanel,
ResizableHandle
} from '@/components/ui/resizable'
<ResizablePanelGroup direction="horizontal" className="min-h-screen">
<ResizablePanel defaultSize={25} minSize={15}>
<div className="p-4">Sidebar</div>
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={75}>
<div className="p-4">Main content</div>
</ResizablePanel>
</ResizablePanelGroup>
Vertical layout:
<ResizablePanelGroup direction="vertical">
<ResizablePanel defaultSize={40}>Header</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={60}>Content</ResizablePanel>
</ResizablePanelGroup>
Responsive resizable (desktop only):
const isDesktop = useMediaQuery('(min-width: 1024px)')
{isDesktop ? (
<ResizablePanelGroup direction="horizontal">
<ResizablePanel>Left</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel>Right</ResizablePanel>
</ResizablePanelGroup>
) : (
<div className="flex flex-col">
<div>Left</div>
<div>Right</div>
</div>
)}
Advanced Responsive Techniques
1. Container Queries (via Tailwind)
<div className="@container">
<div className="@md:grid @md:grid-cols-2 @lg:grid-cols-3">
Container-based responsive grid
</div>
</div>
2. Clamp for Fluid Typography
<h1 style={{ fontSize: 'clamp(1.5rem, 5vw, 3rem)' }}>
Fluid heading size
</h1>
Or with Tailwind arbitrary values:
<h1 className="text-[clamp(1.5rem,5vw,3rem)]">
Fluid heading
</h1>
3. Dynamic Grid Columns
const GridLayout = ({ itemCount }: { itemCount: number }) => {
const columns = itemCount < 4 ? itemCount :
itemCount < 8 ? 2 :
itemCount < 12 ? 3 : 4
return (
<div className={`grid gap-4`} style={{
gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`
}}>
{items.map(item => <Card key={item.id} />)}
</div>
)
}
4. Responsive Image Optimization
<picture>
<source
media="(min-width: 1024px)"
srcSet="/image-large.jpg"
/>
<source
media="(min-width: 768px)"
srcSet="/image-medium.jpg"
/>
<img
src="/image-small.jpg"
alt="..."
className="w-full h-auto"
/>
</picture>
5. Scroll Behavior
// Horizontal scroll on mobile, grid on desktop
<div className="flex overflow-x-auto md:grid md:grid-cols-3 gap-4 pb-4 md:pb-0">
{items.map(item => (
<div key={item.id} className="flex-shrink-0 w-64 md:w-auto">
<Card {...item} />
</div>
))}
</div>
Common Layout Patterns
1. Holy Grail Layout
<div className="min-h-screen flex flex-col">
{/* Header */}
<header className="h-16 border-b">Header</header>
{/* Main content area */}
<div className="flex-1 flex flex-col lg:flex-row">
{/* Left sidebar - mobile: full width, desktop: fixed width */}
<aside className="lg:w-64 border-b lg:border-r lg:border-b-0">
Sidebar
</aside>
{/* Main content */}
<main className="flex-1 p-4 lg:p-8">
Content
</main>
{/* Right sidebar - hidden on mobile/tablet */}
<aside className="hidden xl:block w-64 border-l">
Right sidebar
</aside>
</div>
{/* Footer */}
<footer className="h-16 border-t">Footer</footer>
</div>
2. Card Grid with Featured Item
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{/* Featured card - spans 2 columns on desktop */}
<div className="md:col-span-2 lg:row-span-2">
<FeaturedCard />
</div>
{/* Regular cards */}
{cards.map(card => (
<div key={card.id}>
<Card {...card} />
</div>
))}
</div>
3. Sidebar Overlay (Mobile) / Fixed (Desktop)
const [sidebarOpen, setSidebarOpen] = useState(false)
const isDesktop = useMediaQuery('(min-width: 1024px)')
<div className="flex">
{/* Mobile overlay */}
{!isDesktop && sidebarOpen && (
<>
<div
className="fixed inset-0 bg-black/50 z-40"
onClick={() => setSidebarOpen(false)}
/>
<aside className="fixed left-0 top-0 h-full w-64 bg-white z-50">
Sidebar
</aside>
</>
)}
{/* Desktop fixed sidebar */}
{isDesktop && (
<aside className="w-64 border-r">
Sidebar
</aside>
)}
<main className="flex-1">
Content
</main>
</div>
4. Responsive Table
{/* Desktop: table, Mobile: cards */}
<div className="hidden md:block">
<table className="w-full">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Role</th>
</tr>
</thead>
<tbody>
{users.map(user => (
<tr key={user.id}>
<td>{user.name}</td>
<td>{user.email}</td>
<td>{user.role}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="md:hidden space-y-4">
{users.map(user => (
<div key={user.id} className="border rounded-lg p-4">
<div className="font-bold">{user.name}</div>
<div className="text-sm text-zinc-500">{user.email}</div>
<div className="text-sm">{user.role}</div>
</div>
))}
</div>
Performance Considerations
- Avoid layout shift - Reserve space for content that loads
- Use CSS over JS - Prefer Tailwind breakpoints over
useMediaQuerywhen possible - Lazy load off-screen content - Especially on mobile
- Optimize images - Use responsive images and modern formats (WebP, AVIF)
- Test on real devices - Emulators don't always reflect real performance
Testing Checklist
When creating responsive layouts, verify:
- Works at all standard breakpoints (320px, 375px, 768px, 1024px, 1440px, 1920px)
- Touch targets are at least 44x44px on mobile
- Text is readable without zooming (minimum 16px on mobile)
- No horizontal scroll at any breakpoint
- Navigation is accessible on all screen sizes
- Images scale appropriately
- Forms are usable on mobile
- Content hierarchy is maintained across breakpoints
Your Role
When asked to create responsive layouts:
- Clarify the content priority - What's most important on mobile?
- Choose the right layout system - Grid, Flexbox, or hybrid
- Start mobile-first - Build up from smallest screen
- Use appropriate breakpoints - Based on content, not arbitrary device sizes
- Provide complete code - Including all responsive variants
- Consider edge cases - Very small screens, very large screens, landscape orientation
- Optimize for touch - On mobile devices
- Test thoroughly - Provide guidance on testing approach
Always favor CSS-based responsive design using Tailwind's breakpoint system over JavaScript-based solutions, and only use hooks like useMediaQuery when you need to fundamentally change component behavior, not just styling.
スコア
総合スコア
リポジトリの品質指標に基づく評価
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
レビュー
レビュー機能は近日公開予定です