# Mobile-First Patterns Comprehensive responsive CSS patterns learned from real-world implementation failures. ## Hero Sections ### Problem 2-column grid layouts leave empty space when one column is hidden on mobile. ### Solution Switch from `display: grid` to `display: flex` on mobile. ```css /* Desktop: 2-column grid */ .hero { display: grid; grid-template-columns: 1fr 1fr; gap: 64px; align-items: center; padding: 80px 0; } /* Mobile: Centered flex */ @media (max-width: 768px) { .hero { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 40px 20px; gap: 24px; } .hero-content { align-items: center; } .hero-badge { align-self: center; } .hero-title { font-size: 32px; text-align: center; } .hero-subtitle { font-size: 14px; text-align: center; } .hero-cta { flex-direction: column; align-items: center; width: 100%; } .hero-cta .btn { width: 100%; max-width: 280px; } .hero-visual { display: none; } } ``` **Key Rule**: Grid reserves space for hidden columns. Flex doesn't. --- ## Large Selection Lists ### Problem Horizontal scroll for 20+ items is unusable on mobile — text gets cut off. ### Solution Collapsible accordion with category headers. ```tsx function MobileSelector({ categories }) { const [expanded, setExpanded] = useState(null); return (
{categories.map(cat => (
{cat.items.map(item => ( ))}
))}
); } ``` ```css .category-items { display: flex; flex-wrap: wrap; gap: 8px; } @media (max-width: 768px) { .category-items { display: none; } .category.expanded .category-items { display: flex; flex-direction: column; padding: 12px; background: var(--bg-secondary); border-radius: 8px; } } ``` --- ## Form Layouts ### Problem Multi-column form layouts get cut off on mobile. ### Solution Stack vertically with full width. ```css .form-row { display: flex; gap: 16px; } .form-group { flex: 1; } @media (max-width: 768px) { .form-row { flex-direction: column; } .form-group { width: 100%; } .form-row.half-width { /* Even "half width" fields go full on mobile */ flex-direction: column; } } ``` --- ## Status/Alert Cards ### Problem Inconsistent text alignment when stacking horizontal elements vertically. ### Solution Both `align-items: center` AND `text-align: center`. ```css .alert { display: flex; align-items: flex-start; gap: 12px; padding: 16px; border-radius: 8px; } .alert-icon { flex-shrink: 0; } .alert-content { flex: 1; } @media (max-width: 768px) { .alert { flex-direction: column; align-items: center; /* Center flex items */ text-align: center; /* Center text within items */ gap: 8px; } .alert-content { text-align: center; /* Explicit for nested elements */ } .alert strong { text-align: center; /* Block elements need explicit */ } } ``` **Key Rule**: Stacked flex items need BOTH `align-items: center` AND `text-align: center`. --- ## Grid Layouts ### Universal Mobile Collapse ```css .pricing-grid, .feature-grid, .team-grid, .stats-grid, .testimonial-grid { display: grid; gap: 24px; } /* Desktop configurations */ .pricing-grid { grid-template-columns: repeat(3, 1fr); } .feature-grid { grid-template-columns: repeat(3, 1fr); } .team-grid { grid-template-columns: repeat(4, 1fr); } .stats-grid { grid-template-columns: repeat(4, 1fr); } .testimonial-grid { grid-template-columns: repeat(2, 1fr); } /* Tablet */ @media (max-width: 1024px) { .team-grid { grid-template-columns: repeat(2, 1fr); } .stats-grid { grid-template-columns: repeat(2, 1fr); } } /* Mobile: Everything single column */ @media (max-width: 768px) { .pricing-grid, .feature-grid, .team-grid, .stats-grid, .testimonial-grid { grid-template-columns: 1fr; } } ``` --- ## Navigation ### Mobile Menu Pattern ```tsx function MobileNav() { const [open, setOpen] = useState(false); return ( <> {/* Mobile menu button */} {/* Mobile menu overlay */}
setOpen(false)} /> {/* Mobile menu panel */} ); } ``` --- ## Form Element Consistency ### Always Style as a Group ```css /* WRONG - Only targets input */ .input { border: 2px solid var(--border); border-radius: 8px; } /* CORRECT - All form fields */ .input, .select, .textarea { border: 2px solid var(--border); border-radius: 8px; padding: 12px 16px; font-size: 16px; /* Prevents iOS zoom */ background: var(--bg-secondary); color: var(--text-primary); } ``` ### Textarea Border Radius Exception Pill-shaped inputs look wrong on textareas: ```css .input, .select { border-radius: 100px; /* Pill shape */ } .textarea { border-radius: 16px; /* Softer, but not pill */ } ``` ### Dropdown Option Styling `