Devlog 21: Mobile-First CSS - Building Responsive UI With Tailwind
78% of Tuggy's traffic is mobile. Desktop is the minority. So I design for mobile first, then enhance for larger screens.
Here's my approach with Tailwind CSS.
Mobile-First Breakpoints
Start with mobile, add complexity for larger screens:
<div class="
p-4 /* Mobile: 16px padding */
md:p-6 /* Tablet: 24px padding */
lg:p-8 /* Desktop: 32px padding */
">
Not the reverse (desktop-first would be p-8 md:p-6 sm:p-4).
Touch Target Sizes
Minimum 44x44px for tap targets (Apple guideline). This is crucial for making taps feel accurate, especially combined with removing the 300ms touch delay:
<button class="
min-w-[44px]
min-h-[44px]
p-3
rounded-lg
">
Vote
</button>
Bigger than you think! But necessary for thumbs.
Responsive Typography
Scale font sizes with viewport:
<h1 class="
text-2xl /* Mobile: 24px */
md:text-3xl /* Tablet: 30px */
lg:text-4xl /* Desktop: 36px */
font-bold
">
{matchup.title}
</h1>
Tailwind's default scale works well.
Layout Patterns
Mobile: Stack vertically
<div class="flex flex-col gap-4">
<div>Content A</div>
<div>Content B</div>
</div>
Desktop: Side by side
<div class="flex flex-col md:flex-row gap-4">
<div class="md:w-1/2">Content A</div>
<div class="md:w-1/2">Content B</div>
</div>
Column on mobile, row on desktop.
Voting Area Layout
Mobile gets full width buttons:
<div class="
grid grid-cols-2 gap-4 /* Mobile: 2 columns */
md:grid-cols-1 md:gap-6 /* Desktop: 1 column per side */
">
<VoteButton side="a" />
<VoteButton side="b" />
</div>
Big tappable areas on mobile.
Safe Areas (iOS Notch)
Handle notches and home indicators:
/* In global CSS */
:root {
--safe-area-inset-top: env(safe-area-inset-top);
--safe-area-inset-bottom: env(safe-area-inset-bottom);
}
<header class="
pt-[var(--safe-area-inset-top)]
px-4
">
<!-- Header content -->
</header>
Content doesn't hide behind notch.
Horizontal Scrolling (Swipe)
For upgrade shop on mobile:
<div class="
overflow-x-auto
flex gap-4
snap-x snap-mandatory
px-4
-mx-4
">
{#each upgrades as upgrade}
<div class="
min-w-[280px]
snap-center
">
<UpgradeCard {upgrade} />
</div>
{/each}
</div>
Swipeable carousel feels native.
Sticky Elements
Vote button always visible:
<button class="
sticky bottom-4
md:relative md:bottom-0
z-10
">
Cast Vote
</button>
Sticky on mobile, static on desktop.
Dark Mode
Use Tailwind's dark mode:
<div class="
bg-white dark:bg-gray-900
text-gray-900 dark:text-white
">
Respects system preference:
// tailwind.config.js
module.exports = {
darkMode: 'media', // or 'class' for manual toggle
}
Performance: Purge CSS
Only include used classes:
// tailwind.config.js
module.exports = {
content: ['./src/**/*.{html,js,svelte,ts}'],
}
Reduces CSS bundle from 3MB to ~10KB.
Custom Utilities
For Tuggy-specific patterns:
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
'tuggy': {
500: '#e94569',
600: '#d63456',
}
},
spacing: {
'safe-top': 'env(safe-area-inset-top)',
'safe-bottom': 'env(safe-area-inset-bottom)',
}
}
}
}
Use like: bg-tuggy-500, pt-safe-top.
Responsive Images
<img
src={imageUrl}
srcset="
{imageUrl}?w=400 400w,
{imageUrl}?w=800 800w,
{imageUrl}?w=1200 1200w
"
sizes="
(max-width: 640px) 100vw,
(max-width: 1024px) 50vw,
33vw
"
alt={alt}
class="w-full h-auto"
loading="lazy"
/>
Serves appropriate size per device.
Testing Responsive Layouts
Chrome DevTools device emulation:
- iPhone SE (small)
- iPhone 13 (medium)
- iPad (tablet)
- Desktop 1920px
Also test on real devices. Emulation isn't perfect.
Common Mobile Issues I Hit
Issue 1: Text too small
Mobile Safari auto-zooms if text < 16px. Keep base font 16px+.
Issue 2: Buttons too close
Need 8px+ gap between tap targets to avoid misclicks.
Issue 3: Horizontal scroll
Elements wider than viewport cause annoying horizontal scroll. Use max-w-full to constrain.
Issue 4: Fixed positioning
position: fixed breaks on mobile when keyboard opens. Use position: sticky instead.
Takeaway
Mobile-first means designing for constraints first, then adding enhancements for larger screens.
Touch targets need to be way bigger than mouse targets. 44x44px minimum.
Tailwind's utility-first approach makes responsive design straightforward. Just add breakpoint prefixes.
Test on real devices. Emulators miss iOS quirks like safe areas and the notch.
Purge unused CSS. Tailwind is huge until you purge. After purging, tiny.
CSS is just one part of mobile optimization. Combine this with touch interaction optimizations like removing the 300ms delay and adding haptic feedback for a complete mobile experience.
Next: performance profiling and optimization techniques.