mobile-ux-improver
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMobile UX Improver
移动端UX优化工具
Purpose
用途
Enforce mobile-first UX best practices to ensure exceptional mobile web experiences. This skill prevents common mobile UX mistakes and guides implementation of touch-friendly, responsive, performant interfaces.
强制执行移动端优先的UX最佳实践,确保卓越的移动端Web体验。本工具可避免常见的移动端UX错误,指导实现适合触摸操作、响应式、高性能的界面。
When to Use
使用场景
Auto-triggers when:
- Editing mobile UI components
- Working with responsive layouts
- Implementing touch interactions
- Optimizing mobile performance
- Using Tailwind responsive classes (sm:, md:, lg:)
- Handling mobile gestures
Manual trigger when:
- Reviewing mobile UX
- Implementing new mobile features
- Debugging mobile-specific issues
自动触发场景:
- 编辑移动端UI组件
- 处理响应式布局
- 实现触摸交互
- 优化移动端性能
- 使用Tailwind响应式类(sm:, md:, lg:)
- 处理移动端手势
手动触发场景:
- 审核移动端UX
- 实现新的移动端功能
- 调试移动端特定问题
Quick Reference
快速参考
Touch Targets
触摸目标
Minimum Sizes:
- ✅ 48px × 48px (recommended)
- ⚠️ 44px × 44px (absolute minimum)
- ❌ < 44px (too small, avoid)
Spacing:
- 8px minimum between interactive elements
- 12px+ recommended for frequently used controls
最小尺寸:
- ✅ 48px × 48px(推荐)
- ⚠️ 44px × 44px(绝对最小值)
- ❌ < 44px(过小,避免使用)
间距:
- 交互元素之间最小间距为8px
- 常用控件建议间距为12px以上
Responsive Breakpoints (Tailwind)
响应式断点(Tailwind)
typescript
// Mobile-first approach
<div className="w-full md:w-1/2 lg:w-1/3">
// Breakpoints
sm: 640px // Small tablets
md: 768px // Tablets
lg: 1024px // Small desktops
xl: 1280px // Large desktops
2xl: 1536px // Extra largetypescript
// Mobile-first approach
<div className="w-full md:w-1/2 lg:w-1/3">
// Breakpoints
sm: 640px // Small tablets
md: 768px // Tablets
lg: 1024px // Small desktops
xl: 1280px // Large desktops
2xl: 1536px // Extra largePerformance Targets
性能指标
- First Contentful Paint: < 1.8s
- Time to Interactive: < 3.8s
- Cumulative Layout Shift: < 0.1
- Largest Contentful Paint: < 2.5s
- 首次内容绘制(First Contentful Paint):< 1.8s
- 可交互时间(Time to Interactive):< 3.8s
- 累积布局偏移(Cumulative Layout Shift):< 0.1
- 最大内容绘制(Largest Contentful Paint):< 2.5s
Core Principles
核心原则
1. Mobile-First Design
1. 移动端优先设计
Always start with mobile layout:
typescript
// ✅ CORRECT - Mobile first, then desktop
<button className="w-full px-4 py-3 md:w-auto md:px-6">
Tap Me
</button>
// ❌ WRONG - Desktop first
<button className="w-auto px-6 sm:w-full sm:px-4">
Tap Me
</button>Why: Mobile constraints force better UX decisions, easier to scale up than down.
始终从移动端布局开始:
typescript
// ✅ 正确 - 先移动端,后桌面端
<button className="w-full px-4 py-3 md:w-auto md:px-6">
点击我
</button>
// ❌ 错误 - 先桌面端
<button className="w-auto px-6 sm:w-full sm:px-4">
点击我
</button>原因: 移动端的限制能促使做出更优的UX决策,从移动端扩展到桌面端比反向操作更简单。
2. Touch-Friendly Targets
2. 适合触摸操作的目标区域
Minimum interactive area:
typescript
// ✅ CORRECT - 48px touch target
<button className="min-h-[48px] min-w-[48px] p-3">
<Icon className="w-6 h-6" />
</button>
// ❌ WRONG - Too small
<button className="p-1">
<Icon className="w-4 h-4" />
</button>Spacing between targets:
typescript
// ✅ CORRECT - Adequate spacing
<div className="flex gap-3">
<button className="p-3">A</button>
<button className="p-3">B</button>
</div>
// ❌ WRONG - Targets too close
<div className="flex gap-1">
<button className="p-1">A</button>
<button className="p-1">B</button>
</div>最小交互区域:
typescript
// ✅ 正确 - 48px触摸目标
<button className="min-h-[48px] min-w-[48px] p-3">
<Icon className="w-6 h-6" />
</button>
// ❌ 错误 - 尺寸过小
<button className="p-1">
<Icon className="w-4 h-4" />
</button>目标区域间距:
typescript
// ✅ 正确 - 间距充足
<div className="flex gap-3">
<button className="p-3">A</button>
<button className="p-3">B</button>
</div>
// ❌ 错误 - 目标区域过近
<div className="flex gap-1">
<button className="p-1">A</button>
<button className="p-1">B</button>
</div>3. Responsive Typography
3. 响应式排版
Use relative units for mobile:
typescript
// ✅ CORRECT - Scales with viewport
<h1 className="text-2xl md:text-4xl lg:text-5xl">
Heading
</h1>
// ✅ CORRECT - Clamp for fluid scaling
<p className="text-base leading-relaxed">
Body text
</p>
// ⚠️ AVOID - Fixed pixel sizes
<h1 style={{ fontSize: '60px' }}>
Heading
</h1>移动端使用相对单位:
typescript
// ✅ 正确 - 随视口缩放
<h1 className="text-2xl md:text-4xl lg:text-5xl">
标题
</h1>
// ✅ 正确 - 使用clamp实现流畅缩放
<p className="text-base leading-relaxed">
正文文本
</p>
// ⚠️ 避免 - 固定像素尺寸
<h1 style={{ fontSize: '60px' }}>
标题
</h1>4. Viewport Configuration
4. 视口配置
Required meta tag:
html
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">Why maximum-scale=5: Allows zoom for accessibility while preventing excessive zoom accidents.
必填meta标签:
html
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">为什么设置maximum-scale=5: 允许为无障碍需求进行缩放,同时避免过度缩放导致的误操作。
Touch Targets & Spacing
触摸目标与间距
Target Sizing Chart
目标尺寸对照表
| Element Type | Minimum Size | Recommended Size | Spacing |
|---|---|---|---|
| Primary Button | 44px | 48px | 12px |
| Icon Button | 44px | 48px | 8px |
| Link in Text | 44px height | 48px height | 8px vertical |
| Checkbox/Radio | 44px | 48px | 12px |
| Slider Thumb | 44px | 48px | N/A |
| 元素类型 | 最小尺寸 | 推荐尺寸 | 间距 |
|---|---|---|---|
| 主按钮 | 44px | 48px | 12px |
| 图标按钮 | 44px | 48px | 8px |
| 文本链接 | 44px高度 | 48px高度 | 8px垂直间距 |
| 复选框/单选框 | 44px | 48px | 12px |
| 滑块手柄 | 44px | 48px | N/A |
Common Patterns
常见模式
Primary Action Button:
typescript
<button className="w-full px-6 py-4 text-lg font-semibold rounded-lg bg-brand-blue text-white hover:bg-blue-600 active:bg-blue-700 transition-colors min-h-[48px]">
Continue
</button>Icon Button:
typescript
<button
className="p-3 rounded-full hover:bg-gray-100 active:bg-gray-200 transition-colors min-h-[48px] min-w-[48px] flex items-center justify-center"
aria-label="Close"
>
<XIcon className="w-6 h-6" />
</button>List of Links:
typescript
<nav className="space-y-2">
{links.map(link => (
<a
key={link.id}
href={link.url}
className="block px-4 py-3 text-base hover:bg-gray-50 active:bg-gray-100 rounded-lg min-h-[48px]"
>
{link.label}
</a>
))}
</nav>📖 Complete Guide: resources/touch-targets-guide.md
主操作按钮:
typescript
<button className="w-full px-6 py-4 text-lg font-semibold rounded-lg bg-brand-blue text-white hover:bg-blue-600 active:bg-blue-700 transition-colors min-h-[48px]">
继续
</button>图标按钮:
typescript
<button
className="p-3 rounded-full hover:bg-gray-100 active:bg-gray-200 transition-colors min-h-[48px] min-w-[48px] flex items-center justify-center"
aria-label="关闭"
>
<XIcon className="w-6 h-6" />
</button>链接列表:
typescript
<nav className="space-y-2">
{links.map(link => (
<a
key={link.id}
href={link.url}
className="block px-4 py-3 text-base hover:bg-gray-50 active:bg-gray-100 rounded-lg min-h-[48px]"
>
{link.label}
</a>
))}
</nav>📖 完整指南:resources/touch-targets-guide.md
Responsive Design
响应式设计
Mobile-First Approach
移动端优先方法
Start with mobile, enhance for larger screens:
typescript
// Layout structure
<div className="
flex flex-col gap-4 /* Mobile: stack vertically */
md:flex-row md:gap-6 /* Tablet: horizontal */
lg:gap-8 /* Desktop: more spacing */
">
<aside className="w-full md:w-64 lg:w-80">
Sidebar
</aside>
<main className="flex-1">
Content
</main>
</div>从移动端开始,为更大屏幕增强体验:
typescript
// 布局结构
<div className="
flex flex-col gap-4 /* 移动端:垂直堆叠 */
md:flex-row md:gap-6 /* 平板端:水平排列 */
lg:gap-8 /* 桌面端:更大间距 */
">
<aside className="w-full md:w-64 lg:w-80">
侧边栏
</aside>
<main className="flex-1">
内容
</main>
</div>Container Patterns
容器模式
Responsive containers:
typescript
// Full-width on mobile, constrained on desktop
<div className="
w-full px-4 /* Mobile: full width, padding */
md:px-6 /* Tablet: more padding */
lg:max-w-7xl lg:mx-auto lg:px-8 /* Desktop: centered, max width */
">
{children}
</div>响应式容器:
typescript
// 移动端全屏,桌面端受限宽度
<div className="
w-full px-4 /* 移动端:全屏,带内边距 */
md:px-6 /* 平板端:更大内边距 */
lg:max-w-7xl lg:mx-auto lg:px-8 /* 桌面端:居中,最大宽度 */
">
{children}
</div>Grid Layouts
网格布局
Responsive grid:
typescript
<div className="
grid grid-cols-1 gap-4 /* Mobile: 1 column */
sm:grid-cols-2 sm:gap-6 /* Small tablet: 2 columns */
lg:grid-cols-3 lg:gap-8 /* Desktop: 3 columns */
">
{items.map(item => (
<Card key={item.id} {...item} />
))}
</div>响应式网格:
typescript
<div className="
grid grid-cols-1 gap-4 /* 移动端:1列 */
sm:grid-cols-2 sm:gap-6 /* 小平板:2列 */
lg:grid-cols-3 lg:gap-8 /* 桌面端:3列 */
">
{items.map(item => (
<Card key={item.id} {...item} />
))}
</div>Hiding/Showing Elements
元素显示/隐藏
Conditional visibility:
typescript
// Mobile menu vs desktop nav
<>
{/* Mobile menu button */}
<button className="md:hidden p-3">
<MenuIcon />
</button>
{/* Desktop navigation */}
<nav className="hidden md:flex gap-6">
<NavLink href="/about">About</NavLink>
<NavLink href="/contact">Contact</NavLink>
</nav>
</>📖 Complete Guide: resources/responsive-patterns.md
条件可见性:
typescript
// 移动端菜单 vs 桌面端导航
<>
{/* 移动端菜单按钮 */}
<button className="md:hidden p-3">
<MenuIcon />
</button>
{/* 桌面端导航 */}
<nav className="hidden md:flex gap-6">
<NavLink href="/about">关于我们</NavLink>
<NavLink href="/contact">联系我们</NavLink>
</nav>
</>📖 完整指南:resources/responsive-patterns.md
Mobile Gestures
移动端手势
Horizontal Scrolling
横向滚动
Swipeable container:
typescript
<div className="
flex gap-4 overflow-x-auto snap-x snap-mandatory
scrollbar-hide /* Hide scrollbar on mobile */
pb-4 /* Padding for scroll indicator */
-mx-4 px-4 /* Edge-to-edge on mobile */
md:mx-0 md:px-0 /* Contained on desktop */
">
{items.map(item => (
<div
key={item.id}
className="flex-shrink-0 w-72 snap-center"
>
<Card {...item} />
</div>
))}
</div>可滑动容器:
typescript
<div className="
flex gap-4 overflow-x-auto snap-x snap-mandatory
scrollbar-hide /* 移动端隐藏滚动条 */
pb-4 /* 滚动指示器内边距 */
-mx-4 px-4 /* 移动端边缘到边缘 */
md:mx-0 md:px-0 /* 桌面端容器化 */
">
{items.map(item => (
<div
key={item.id}
className="flex-shrink-0 w-72 snap-center"
>
<Card {...item} />
</div>
))}
</div>Pull-to-Refresh
下拉刷新
Implement with overscroll-behavior:
typescript
<main className="
overscroll-contain /* Prevent chain scrolling */
overflow-y-auto
h-screen
">
{content}
</main>使用overscroll-behavior实现:
typescript
<main className="
overscroll-contain /* 防止链式滚动 */
overflow-y-auto
h-screen
">
{content}
</main>Scroll Behavior
滚动行为
Smooth scrolling:
typescript
// Global CSS or Tailwind
<html className="scroll-smooth">
// Component-level
<div className="overflow-y-auto scroll-smooth">
{longContent}
</div>📖 Complete Guide: resources/mobile-gestures.md
平滑滚动:
typescript
// 全局CSS或Tailwind
<html className="scroll-smooth">
// 组件级
<div className="overflow-y-auto scroll-smooth">
{longContent}
</div>📖 完整指南:resources/mobile-gestures.md
Performance Optimization
性能优化
Image Optimization
图片优化
Responsive images:
typescript
<img
src="/hero-mobile.jpg"
srcSet="
/hero-mobile.jpg 640w,
/hero-tablet.jpg 1024w,
/hero-desktop.jpg 1920w
"
sizes="
(max-width: 640px) 100vw,
(max-width: 1024px) 50vw,
33vw
"
alt="Hero image"
loading="lazy"
className="w-full h-auto"
/>响应式图片:
typescript
<img
src="/hero-mobile.jpg"
srcSet="
/hero-mobile.jpg 640w,
/hero-tablet.jpg 1024w,
/hero-desktop.jpg 1920w
"
sizes="
(max-width: 640px) 100vw,
(max-width: 1024px) 50vw,
33vw
"
alt="Hero image"
loading="lazy"
className="w-full h-auto"
/>Lazy Loading
懒加载
Component lazy loading:
typescript
import { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function Page() {
return (
<Suspense fallback={<LoadingSpinner />}>
<HeavyComponent />
</Suspense>
);
}组件懒加载:
typescript
import { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function Page() {
return (
<Suspense fallback={<LoadingSpinner />}>
<HeavyComponent />
</Suspense>
);
}Font Loading
字体加载
Optimize web fonts:
html
<link
rel="preload"
href="/fonts/custom-font.woff2"
as="font"
type="font/woff2"
crossorigin
/>📖 Complete Guide: resources/mobile-performance.md
优化Web字体:
html
<link
rel="preload"
href="/fonts/custom-font.woff2"
as="font"
type="font/woff2"
crossorigin
/>📖 完整指南:resources/mobile-performance.md
Accessibility for Mobile
移动端无障碍访问
Screen Reader Support
屏幕阅读器支持
Proper labeling:
typescript
<button
aria-label="Close dialog"
className="p-3"
>
<XIcon className="w-6 h-6" />
</button>正确标注:
typescript
<button
aria-label="关闭对话框"
className="p-3"
>
<XIcon className="w-6 h-6" />
</button>Focus Management
焦点管理
Keyboard + touch support:
typescript
<button className="
p-3 rounded-lg
focus:outline-none focus:ring-2 focus:ring-brand-blue focus:ring-offset-2
active:bg-gray-100
">
Action
</button>键盘+触摸支持:
typescript
<button className="
p-3 rounded-lg
focus:outline-none focus:ring-2 focus:ring-brand-blue focus:ring-offset-2
active:bg-gray-100
">
操作
</button>Color Contrast
颜色对比度
WCAG AA minimum:
- Normal text: 4.5:1
- Large text: 3:1
- Interactive elements: 3:1
WCAG AA最低标准:
- 普通文本:4.5:1
- 大文本:3:1
- 交互元素:3:1
Common Anti-Patterns to Avoid
需避免的常见反模式
❌ Don't: Hover-Only Interactions
❌ 不要:仅支持悬停的交互
typescript
// ❌ WRONG - No hover on touch devices
<div className="hover:visible">
Hidden content
</div>
// ✅ CORRECT - Click/tap to reveal
<button onClick={() => setVisible(true)}>
Show content
</button>typescript
// ❌ 错误 - 触摸设备无悬停功能
<div className="hover:visible">
隐藏内容
</div>
// ✅ 正确 - 点击/触摸显示
<button onClick={() => setVisible(true)}>
显示内容
</button>❌ Don't: Fixed Positioning That Blocks Content
❌ 不要:固定定位遮挡内容
typescript
// ❌ WRONG - Header blocks content
<header className="fixed top-0 w-full h-16 bg-white">
<main className="pt-0"> /* Content hidden behind header */
// ✅ CORRECT - Account for header
<header className="fixed top-0 w-full h-16 bg-white z-10">
<main className="pt-16"> /* Content starts below header */typescript
// ❌ 错误 - 头部遮挡内容
<header className="fixed top-0 w-full h-16 bg-white">
<main className="pt-0"> /* 内容被头部遮挡 */
// ✅ 正确 - 为头部预留空间
<header className="fixed top-0 w-full h-16 bg-white z-10">
<main className="pt-16"> /* 内容从头部下方开始 */❌ Don't: Tiny Text
❌ 不要:过小文本
typescript
// ❌ WRONG - Unreadable on mobile
<p className="text-xs">
Important information
</p>
// ✅ CORRECT - Readable base size
<p className="text-base md:text-sm">
Important information
</p>typescript
// ❌ 错误 - 移动端无法阅读
<p className="text-xs">
重要信息
</p>
// ✅ 正确 - 可读的基础尺寸
<p className="text-base md:text-sm">
重要信息
</p>❌ Don't: Disable Zoom
❌ 不要:禁用缩放
html
<!-- ❌ WRONG - Prevents accessibility -->
<meta name="viewport" content="user-scalable=no, maximum-scale=1">
<!-- ✅ CORRECT - Allow zoom for accessibility -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">html
<!-- ❌ 错误 - 影响无障碍访问 -->
<meta name="viewport" content="user-scalable=no, maximum-scale=1">
<!-- ✅ 正确 - 允许为无障碍需求缩放 -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">Example: Mobile-Optimized Component
示例:移动端优化组件
Complete touch-friendly card:
typescript
import React from 'react';
interface ProductCardProps {
title: string;
price: number;
image: string;
onAddToCart: () => void;
}
export const ProductCard: React.FC<ProductCardProps> = ({
title,
price,
image,
onAddToCart
}) => {
return (
<div className="
bg-white rounded-lg shadow-sm overflow-hidden
hover:shadow-md transition-shadow
w-full /* Mobile: full width */
sm:w-64 /* Tablet: fixed width */
">
<img
src={image}
alt={title}
loading="lazy"
className="w-full h-48 object-cover"
/>
<div className="p-4">
<h3 className="text-lg font-semibold mb-2 line-clamp-2">
{title}
</h3>
<p className="text-2xl font-bold text-brand-blue mb-4">
${price.toFixed(2)}
</p>
<button
onClick={onAddToCart}
className="
w-full px-6 py-3 rounded-lg
bg-brand-blue text-white font-semibold
hover:bg-blue-600 active:bg-blue-700
transition-colors
min-h-[48px] /* Touch-friendly height */
focus:outline-none focus:ring-2 focus:ring-brand-blue focus:ring-offset-2
"
aria-label={`Add ${title} to cart`}
>
Add to Cart
</button>
</div>
</div>
);
};
export default ProductCard;完整的触摸友好型卡片:
typescript
import React from 'react';
interface ProductCardProps {
title: string;
price: number;
image: string;
onAddToCart: () => void;
}
export const ProductCard: React.FC<ProductCardProps> = ({
title,
price,
image,
onAddToCart
}) => {
return (
<div className="
bg-white rounded-lg shadow-sm overflow-hidden
hover:shadow-md transition-shadow
w-full /* 移动端:全屏 */
sm:w-64 /* 平板端:固定宽度 */
">
<img
src={image}
alt={title}
loading="lazy"
className="w-full h-48 object-cover"
/>
<div className="p-4">
<h3 className="text-lg font-semibold mb-2 line-clamp-2">
{title}
</h3>
<p className="text-2xl font-bold text-brand-blue mb-4">
${price.toFixed(2)}
</p>
<button
onClick={onAddToCart}
className="
w-full px-6 py-3 rounded-lg
bg-brand-blue text-white font-semibold
hover:bg-blue-600 active:bg-blue-700
transition-colors
min-h-[48px] /* 适合触摸的高度 */
focus:outline-none focus:ring-2 focus:ring-brand-blue focus:ring-offset-2
"
aria-label={`Add ${title} to cart`}
>
加入购物车
</button>
</div>
</div>
);
};
export default ProductCard;Testing Mobile UX
移动端UX测试
Manual Testing Checklist
手动检查清单
- Test on real mobile devices (iOS, Android)
- Verify touch targets are 44px+ minimum
- Check text is readable without zoom
- Test horizontal scrolling with touch
- Verify forms work with mobile keyboards
- Test landscape + portrait orientations
- Check performance on slow connections
- Verify hover states have touch alternatives
- Test with screen reader (VoiceOver, TalkBack)
- Check color contrast meets WCAG AA
- 在真实移动设备(iOS、Android)上测试
- 验证触摸目标最小尺寸为44px+
- 检查文本无需缩放即可阅读
- 测试触摸横向滚动
- 验证表单在移动端键盘下可正常使用
- 测试横屏+竖屏方向
- 在慢速网络下测试性能
- 验证悬停状态有触摸替代方案
- 使用屏幕阅读器(VoiceOver、TalkBack)测试
- 检查颜色对比度符合WCAG AA标准
Browser DevTools
浏览器开发者工具
Chrome DevTools Mobile Emulation:
- Open DevTools (F12)
- Toggle device toolbar (Cmd+Shift+M / Ctrl+Shift+M)
- Select device or custom dimensions
- Enable touch emulation
- Test throttling (3G, 4G networks)
Chrome DevTools移动端模拟:
- 打开DevTools(F12)
- 切换设备工具栏(Cmd+Shift+M / Ctrl+Shift+M)
- 选择设备或自定义尺寸
- 启用触摸模拟
- 测试网络节流(3G、4G网络)
Reference Existing Components
参考现有组件
Good examples in your codebase:
- - Touch-friendly pill buttons with proper spacing
FilterPill.tsx - - Responsive card layout with touch interactions
TeamCard.tsx - - Floating action button with proper touch target
Fab.tsx
代码库中的优秀示例:
- - 触摸友好的胶囊按钮,间距合理
FilterPill.tsx - - 响应式卡片布局,支持触摸交互
TeamCard.tsx - - 浮动操作按钮,触摸目标尺寸合规
Fab.tsx
Related Skills
相关技能
- frontend-dev-guidelines: React/TypeScript best practices
- seo-specialist: Mobile SEO optimization
- error-tracking: Performance monitoring
Skill Status: Active guardrail - Enforces mobile UX quality
Line Count: < 500 (following 500-line rule) ✅
Progressive Disclosure: Reference files for detailed guides ✅
- frontend-dev-guidelines: React/TypeScript最佳实践
- seo-specialist: 移动端SEO优化
- error-tracking: 性能监控
技能状态:激活状态 - 强制执行移动端UX质量标准
代码行数:< 500(符合500行规则)✅
渐进式披露:参考文件获取详细指南 ✅