8.2 KiB
8.2 KiB
Responsive Design
Mobile-first responsive design using Tailwind CSS breakpoints. Works beautifully on all devices from 320px to 1920px+.
Breakpoints
| Breakpoint | Min Width | Device | Container |
|---|---|---|---|
| (none) | 0px | Mobile | 100% |
sm |
640px | Large phone | 640px |
md |
768px | Tablet | 768px |
lg |
1024px | Laptop | 1024px |
xl |
1280px | Desktop | 1280px |
2xl |
1400px | Large desktop | 1400px (custom) |
Mobile-First Approach
Write for mobile first, enhance for larger screens:
// Mobile (default): text-sm
// Tablet+: text-base
// Desktop+: text-lg
<p className="text-sm md:text-base lg:text-lg">
Responsive text
</p>
// Mobile: 1 column, Tablet: 2, Desktop: 3
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
{items}
</div>
Common Responsive Patterns
Responsive Grid
// Game card grid
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
{games.map((game) => (
<GameCard key={game.id} game={game} />
))}
</div>
Responsive Typography
// Page title
<h1 className="text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-bold">
Welcome to Flashpoint
</h1>
// Body text
<p className="text-sm md:text-base lg:text-lg leading-relaxed">
Browse and play thousands of games.
</p>
// Section heading
<h2 className="text-2xl md:text-3xl lg:text-4xl font-semibold mb-4 md:mb-6">
Popular Games
</h2>
Responsive Spacing
// Container padding
<div className="container mx-auto px-4 md:px-6 lg:px-8">
Content
</div>
// Section margins
<section className="mb-8 md:mb-12 lg:mb-16">
Section content
</section>
// Gap between items
<div className="flex gap-2 sm:gap-4 md:gap-6">
{items}
</div>
Responsive Layout
// Two-column layout
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6 lg:gap-8">
{/* Sidebar - full width mobile, 3 cols desktop */}
<aside className="lg:col-span-3">
<FilterPanel />
</aside>
{/* Main - full width mobile, 9 cols desktop */}
<main className="lg:col-span-9">
<GameGrid />
</main>
</div>
// Split view (stacks mobile, splits desktop)
<div className="flex flex-col md:flex-row gap-6">
<div className="md:w-1/2">Left panel</div>
<div className="md:w-1/2">Right panel</div>
</div>
Responsive Navigation
// Desktop horizontal, mobile vertical
<nav className="flex flex-col md:flex-row gap-4 md:gap-8">
<NavLink to="/">Home</NavLink>
<NavLink to="/browse">Browse</NavLink>
<NavLink to="/favorites">Favorites</NavLink>
</nav>
// Hide/show elements
<div>
{/* Mobile menu button */}
<Button className="md:hidden" onClick={toggleMenu}>
<Menu className="h-6 w-6" />
</Button>
{/* Desktop navigation */}
<nav className="hidden md:flex items-center gap-6">
<NavLink to="/">Home</NavLink>
<NavLink to="/browse">Browse</NavLink>
</nav>
</div>
Responsive Components
Header
function Header() {
return (
<header className="border-b border-border">
<div className="container mx-auto px-4 md:px-6">
<div className="flex items-center justify-between h-14 md:h-16 lg:h-20">
<Logo className="h-8 md:h-10 lg:h-12" />
<nav className="hidden lg:flex items-center gap-6">
<NavLink to="/">Home</NavLink>
<NavLink to="/browse">Browse</NavLink>
</nav>
<div className="flex items-center gap-2 md:gap-4">
<Button size="sm" className="hidden sm:inline-flex">
Sign In
</Button>
<Button size="icon" className="lg:hidden">
<Menu />
</Button>
</div>
</div>
</div>
</header>
);
}
Game Card
function GameCard({ game }) {
return (
<Card className="hover:shadow-lg transition-shadow">
<div className="aspect-video md:aspect-[4/3] lg:aspect-video overflow-hidden">
<img
src={game.image}
alt={game.title}
className="w-full h-full object-cover"
/>
</div>
<CardHeader className="p-3 md:p-4 lg:p-6">
<CardTitle className="text-base md:text-lg lg:text-xl line-clamp-2">
{game.title}
</CardTitle>
</CardHeader>
<CardFooter className="p-3 md:p-4 lg:p-6 pt-0 flex flex-col sm:flex-row gap-2">
<Button className="flex-1">Play Now</Button>
<Button variant="outline" size="icon">
<Heart className="h-4 w-4" />
</Button>
</CardFooter>
</Card>
);
}
Filter Panel
function FilterPanel() {
return (
<Card className="p-4 md:p-6">
<CardHeader className="p-0 mb-4">
<CardTitle className="text-lg md:text-xl">Filters</CardTitle>
</CardHeader>
<CardContent className="p-0 space-y-4 md:space-y-6">
<div className="space-y-2">
<Label className="text-sm md:text-base">Platform</Label>
<Select>
<SelectTrigger>
<SelectValue placeholder="All Platforms" />
</SelectTrigger>
<SelectContent>
<SelectItem value="flash">Flash</SelectItem>
<SelectItem value="html5">HTML5</SelectItem>
</SelectContent>
</Select>
</div>
{/* Year range - stack mobile, side-by-side tablet+ */}
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<Input type="number" placeholder="From" />
<Input type="number" placeholder="To" />
</div>
</CardContent>
</Card>
);
}
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 display modes
<div className="block md:flex lg:grid">
Changes display mode across breakpoints
</div>
Responsive Utilities
Flex
// Direction
<div className="flex flex-col md:flex-row">
Vertical mobile, horizontal tablet+
</div>
// Alignment
<div className="flex justify-start md:justify-between lg:justify-center">
Different alignment per breakpoint
</div>
Positioning
// Position changes
<div className="static md:relative lg:absolute">
Position varies by breakpoint
</div>
// Z-index
<div className="z-10 md:z-20 lg:z-30">
Higher z-index on larger screens
</div>
Touch-Friendly Design
Minimum Touch Targets
All interactive elements should be 44px × 44px on mobile:
// Good: Large enough
<Button className="h-12 w-12 md:h-10 md:w-10">
<Icon />
</Button>
// Good: Sufficient padding
<button className="px-4 py-3 md:px-3 md:py-2">
Click me
</button>
Mobile Spacing
// Generous spacing on mobile
<div className="space-y-4 md:space-y-3">
{items}
</div>
// Touch-friendly gaps
<div className="flex gap-4 md:gap-2">
<Button>Action 1</Button>
<Button>Action 2</Button>
</div>
Responsive Images
Aspect Ratios
// Fixed ratio
<div className="aspect-square md:aspect-video">
<img src={src} alt={alt} className="w-full h-full object-cover" />
</div>
// Different ratios per breakpoint
<div className="aspect-[4/3] md:aspect-video lg:aspect-[21/9]">
<img src={src} alt={alt} className="w-full h-full object-cover" />
</div>
Responsive Sizing
// Responsive max-width
<img src={src} alt={alt} className="w-full max-w-xs md:max-w-md lg:max-w-lg" />
// Responsive height
<img src={src} alt={alt} className="h-48 md:h-64 lg:h-80 w-auto" />
Testing Breakpoints
Always test at:
- 320px (small mobile)
- 375px (mobile)
- 768px (tablet)
- 1024px (laptop)
- 1440px (desktop)
- 1920px (large desktop)
Best Practices
- Mobile-First Always - Write mobile styles first, add breakpoint prefixes for larger screens
- Progressive Enhancement - Basic on mobile, enhanced on desktop
- Avoid Overuse - Use 2-3 breakpoints, not every breakpoint
- Test All Breakpoints - Don't assume it works without testing
- Consistent Patterns - Reuse responsive patterns across components
Next: Design Patterns - Common UI patterns