Mobile ui design
Mobile-first interface design for touch-optimized, native-feeling web and app UIs. Trigger: user asks to "design for mobile", "build a mobile UI", "make it mobile-friendly", "create a mobile app", "build a responsive mobile layout", "design a bottom sheet", "mobile navigation", or any mobile-specific interface work.From its SKILL.md
npx -y skills add ArnavPuri/designskills --skill mobile-ui-designAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
11.6 KB, as published. Nobody here has run it
Mobile UI Design
Pre-Flight: Check Design Context
Before generating mobile UI code:
- Use
get_design_contextto check for existing design tokens, platform guidelines, or component libraries. - If a Figma URL is provided, pull screenshots and metadata to match the design.
- Determine: Is this a native app (React Native/Flutter), a PWA, or a responsive website?
1. Touch Target Sizes
Every interactive element must be large enough to tap reliably.
Minimum Sizes
| Platform | Minimum Target | Recommended |
|---|---|---|
| Apple HIG | 44x44px | 48x48px |
| Material Design | 48x48px | 56x56px |
| WCAG 2.5.8 | 24x24px (AAA: 44px) | 44x44px |
Implementation
/* Ensure tap targets even on small visual elements */
.icon-button {
width: 24px;
height: 24px;
/* Expand tap target with padding or pseudo-element */
position: relative;
}
.icon-button::after {
content: '';
position: absolute;
inset: -12px; /* extends tap area to 48x48 */
}
Spacing Between Targets
Minimum 8px gap between tappable elements. 12px+ is preferred. This prevents accidental taps.
2. Bottom Navigation
The thumb reaches the bottom of the screen most easily. Put primary navigation there.
Standard Bottom Tab Bar
<nav class="fixed bottom-0 inset-x-0 bg-white border-t border-gray-200
safe-area-bottom z-50">
<div class="flex items-center justify-around h-16">
<!-- Active tab -->
<a href="#" class="flex flex-col items-center gap-0.5 text-indigo-600 min-w-[64px]">
<svg class="w-6 h-6" fill="currentColor"><!-- home icon --></svg>
<span class="text-[10px] font-medium">Home</span>
</a>
<!-- Inactive tab -->
<a href="#" class="flex flex-col items-center gap-0.5 text-gray-400 min-w-[64px]">
<svg class="w-6 h-6" fill="none" stroke="currentColor"><!-- search icon --></svg>
<span class="text-[10px] font-medium">Search</span>
</a>
<!-- ... 3-5 tabs total -->
</div>
</nav>
Rules
- Maximum 5 tabs. 3–4 is ideal.
- Active tab: filled icon + primary color. Inactive: outline icon + gray.
- Labels are required. Icon-only tabs have poor discoverability.
- Never use a hamburger menu as a tab bar replacement.
- Account for bottom safe area on notched devices.
Safe Area CSS
.safe-area-bottom {
padding-bottom: env(safe-area-inset-bottom);
}
3. Gesture-Friendly Interactions
Swipe Actions
<!-- Swipe-to-reveal pattern (conceptual structure) -->
<div class="relative overflow-hidden">
<!-- Background action (revealed on swipe) -->
<div class="absolute inset-y-0 right-0 flex items-center bg-red-500 px-6">
<span class="text-white font-medium">Delete</span>
</div>
<!-- Foreground content (swipeable) -->
<div class="bg-white px-4 py-3 transform transition-transform touch-pan-y">
<div class="font-medium text-gray-900">List Item</div>
<div class="text-sm text-gray-500">Swipe left for actions</div>
</div>
</div>
Pull-to-Refresh
- Indicator appears at top as user pulls down.
- Use a spinner or custom animation.
- Trigger refresh at ~80px pull distance.
- Provide haptic feedback if possible (native only).
Common Mobile Gestures
| Gesture | Use Case | Implementation |
|---|---|---|
| Swipe left/right | Reveal actions, navigate | touch-action: pan-y |
| Pull down | Refresh content | Overscroll detection |
| Long press | Context menu, reorder | @touchstart with timeout |
| Pinch | Zoom images/maps | touch-action: manipulation |
| Swipe up | Dismiss sheet, expand | Drag handle on bottom sheet |
4. iOS vs Android Design Language
Key Differences
| Element | iOS (Human Interface) | Android (Material) |
|---|---|---|
| Navigation | Tab bar at bottom | Bottom navigation bar |
| Back | Swipe from left edge / text "Back" | Arrow icon top-left |
| Titles | Large title that collapses | Centered or left-aligned |
| Buttons | Rounded rect, no elevation | Rounded, with elevation |
| Switches | Green/white toggle | Track + thumb with ripple |
| Sheets | Rounded top, drag handle | Full-width, drag handle |
| Typography | SF Pro (system) | Roboto (system) |
| Spacing | 16px margins | 16px margins |
Cross-Platform Approach
When building for both, lean toward iOS patterns for polish and Material patterns for interaction feedback. Use system fonts:
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
5. Safe Areas
Device Considerations
/* Status bar area */
.top-safe {
padding-top: env(safe-area-inset-top);
}
/* Home indicator / gesture bar */
.bottom-safe {
padding-bottom: env(safe-area-inset-bottom);
}
/* Notch / Dynamic Island on landscape */
.side-safe {
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
/* Full-bleed safe wrapper */
.safe-area {
padding: env(safe-area-inset-top) env(safe-area-inset-right)
env(safe-area-inset-bottom) env(safe-area-inset-left);
}
Viewport Meta
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
The viewport-fit=cover is required for env(safe-area-inset-*) to work.
6. Mobile Typography Scale
Recommended Scale
| Role | Size | Weight | Line Height |
|---|---|---|---|
| Large title | 34px | 700 | 1.2 |
| Title 1 | 28px | 700 | 1.2 |
| Title 2 | 22px | 700 | 1.25 |
| Title 3 | 20px | 600 | 1.25 |
| Headline | 17px | 600 | 1.3 |
| Body | 17px | 400 | 1.5 |
| Callout | 16px | 400 | 1.4 |
| Subhead | 15px | 400 | 1.4 |
| Footnote | 13px | 400 | 1.3 |
| Caption | 12px | 400 | 1.3 |
Rules
- Body text minimum 16px on mobile (prevents iOS zoom on input focus).
- Line length: 35–50 characters max for comfortable mobile reading.
- Use
remunits based on 16px root.
7. Thumb Zone Optimization
The Thumb Zone Map
+-----------------------------+
| Hard to reach | <- Top 25%: Put secondary actions, titles
| |
|-----------------------------|
| Comfortable stretch | <- Middle 50%: Content, scrollable lists
| |
|-----------------------------|
| Easy / Natural | <- Bottom 25%: Primary actions, nav, FAB
+-----------------------------+
Practical Rules
- Primary actions at bottom: CTA buttons, submit buttons, navigation.
- Search bars: Consider bottom placement (like iOS Safari).
- FAB (Floating Action Button): Bottom-right corner, 56px, with shadow.
- Destructive actions at top: Harder to reach = harder to accidentally trigger.
<!-- Bottom-anchored CTA -->
<div class="fixed bottom-0 inset-x-0 p-4 bg-gradient-to-t from-white via-white
to-transparent pt-12 safe-area-bottom">
<button class="w-full bg-indigo-600 text-white py-4 rounded-2xl font-semibold
text-lg active:bg-indigo-700 transition-colors">
Continue
</button>
</div>
8. Sheet / Bottom Drawer Patterns
Bottom Sheet Structure
<div class="fixed inset-0 z-50">
<!-- Backdrop -->
<div class="absolute inset-0 bg-black/40 backdrop-blur-sm"></div>
<!-- Sheet -->
<div class="absolute bottom-0 inset-x-0 bg-white rounded-t-3xl
max-h-[85vh] overflow-y-auto safe-area-bottom">
<!-- Drag handle -->
<div class="flex justify-center pt-3 pb-2">
<div class="w-10 h-1 rounded-full bg-gray-300"></div>
</div>
<!-- Content -->
<div class="px-4 pb-6">
<h2 class="text-xl font-bold text-gray-900 mb-4">Sheet Title</h2>
<!-- Sheet content -->
</div>
</div>
</div>
Sheet Variants
- Peek sheet: Shows 30% of content, drag to expand.
- Action sheet: List of options (iOS-style).
- Full-screen sheet: Slides up to cover entire screen with close button.
- Map sheet: Persistent bottom sheet over a map (Google Maps style).
Sheet Rules
- Always include a drag handle (40px wide, 4px tall, centered, rounded).
- Max height: 85% of viewport. Let it scroll internally.
- Dismiss: swipe down, tap backdrop, or explicit close button.
- Snap points: collapsed, half, expanded.
9. Mobile Form Design
Rules
- Large inputs: Minimum 48px height, 16px+ font (avoids iOS zoom).
- Full-width inputs: Edge-to-edge within the container.
- Smart keyboard types: Use
inputmodeattribute. - Sticky submit button: Fixed at bottom of screen.
- Single column only: Never side-by-side fields on mobile.
Input Mode Attribute
<!-- Phone number: numeric keyboard -->
<input type="tel" inputmode="tel" />
<!-- Email: keyboard with @ and . -->
<input type="email" inputmode="email" />
<!-- Number: numeric keypad -->
<input type="text" inputmode="numeric" pattern="[0-9]*" />
<!-- URL: keyboard with / and .com -->
<input type="url" inputmode="url" />
<!-- Search: keyboard with search/go button -->
<input type="search" inputmode="search" />
Mobile-Optimized Input
<div class="space-y-1.5">
<label for="phone" class="block text-sm font-medium text-gray-700">
Phone number
</label>
<input
type="tel"
id="phone"
inputmode="tel"
autocomplete="tel"
class="block w-full h-12 rounded-xl border border-gray-300 px-4
text-base text-gray-900 placeholder:text-gray-400
focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20"
placeholder="+1 (555) 000-0000"
/>
</div>
10. Native-Feeling Animations
Timing Functions
/* iOS-like spring curve */
--ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
/* Quick in, slow out (for entering elements) */
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
/* Slow in, quick out (for exiting elements) */
--ease-in: cubic-bezier(0.55, 0, 1, 0.45);
Common Transitions
/* Page transition: slide from right */
.page-enter {
transform: translateX(100%);
animation: slide-in 350ms var(--ease-out) forwards;
}
@keyframes slide-in {
to { transform: translateX(0); }
}
/* Sheet reveal: slide up */
.sheet-enter {
transform: translateY(100%);
animation: sheet-up 400ms var(--ease-out) forwards;
}
@keyframes sheet-up {
to { transform: translateY(0); }
}
/* Tap feedback */
.tap-feedback:active {
transform: scale(0.97);
opacity: 0.8;
transition: all 50ms ease;
}
Animation Rules for Mobile
- Keep animations under 400ms. 200–300ms feels snappy.
- Use
transformandopacityonly for 60fps performance. - Add
will-change: transformsparingly for animated elements. - Respect
prefers-reduced-motion:
@media (prefers-reduced-motion: reduce) {
* { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}
- Provide haptic feedback for important actions (native only).
Mobile Design Checklist
- All tap targets are 44px+ minimum
- Bottom navigation with 3–5 tabs and labels
- Safe areas respected (top, bottom, sides)
- Body text is 16px+ (no iOS zoom on focus)
- Primary actions are in the thumb zone (bottom)
- Forms use correct
inputmodeattributes - Sheets have drag handles and dismiss gestures
- Animations are under 400ms and use GPU-friendly properties
-
viewport-fit=covermeta tag is set -
prefers-reduced-motionis respected - Content is readable at 320px width
- No horizontal scroll on any screen