mcpField
M
mobile-ui-design

mobile-ui-design

github.com/arnavpuri设计与 UI17114 次安装4 周前更新
代码仓库

关于 mobile-ui-design

为构建移动界面提供设计指导,面向生成或实现移动端 UI 的 Agent。内容涵盖触控、导航、安全区域、表单、动效及渲染检查,并强调无障碍与不同平台模式。

主要功能

  1. 01加载设计上下文并映射设计令牌
  2. 02触控目标与底部导航规范
  3. 03手势、安全区域及平台模式指导
  4. 04移动端排版与表单建议
  5. 05动效、无障碍及渲染检查

适用场景

  1. 01设计移动端导航与交互布局
  2. 02实现适配安全区域的页面
  3. 03检查移动表单和触控目标
  4. 04生成界面后验证不同视口

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/arnavpuri/designskills --skill mobile-ui-design

安装后在 Claude Code 中输入/mobile-ui-design确认已加载。

详细介绍

移动端 UI 设计

开始之前:加载设计上下文

  1. 阅读 .agents/design-context.md(由 design-context 技能编写)。如果文件不存在,请在 tailwind.config.* 或 :root CSS 变量中查找设计令牌。如果都没有,请使用默认值(主色 #2563EB、辅助色 #7C3AED、强调色 #F59E0B、Tailwind 灰色中性色、标题和正文使用 Inter、极简风格),并告知用户使用了默认值——建议运行 design-context。
  2. 将设计令牌映射为 CSS 变量一次,之后只使用这些变量:--color-primary、--color-primary-light、--color-primary-dark、--color-secondary、--color-accent、--color-neutral-50…--color-neutral-900、--color-success/-warning/-error、--font-heading、--font-body、--font-mono、--radius,以及以 4px 为基准的间距刻度。
  3. **Tailwind:**以 primary、primary-light、primary-dark、secondary、accent、neutral-*、font-heading、font-body 为名,公开相同的变量(v3 使用 theme.extend,v4 使用 @theme)。下方示例中的 indigo-* / gray-* 类是这些设计令牌的占位符。
  4. **Figma:**如果用户提供 Figma URL,请使用 Figma MCP(get_design_context、get_screenshot)获取设计并与之匹配;对于该设计,它优先于上下文文件。
  5. 询问这是原生应用(React Native/Flutter:将设计令牌映射到主题对象,而不是 CSS 变量)、PWA,还是响应式网站。

1. 触控目标尺寸

每个可交互元素都必须足够大,确保用户能够可靠地点击。

最小尺寸
来源最小目标尺寸备注
Apple HIG44×44pt= 网页上的 44×44 CSS px
Material Design48×48dp≈ 48×48 CSS px;图标视觉尺寸可以是 24dp
WCAG 2.2 SC 2.5.8 (AA)24×24 CSS px法律规定的底线,而非设计目标
WCAG 2.2 SC 2.5.5 (AAA)44×44 CSS px

**此技能的规则:**所有触控目标至少为 44×44px(Android 风格 UI 中为 48×48px)。

实现
/* 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 */
}
目标之间的间距

可点击元素之间至少留出 8px 的间隙,建议为 12px 或更大,以避免误触。


2. 底部导航

拇指最容易触及屏幕底部,因此应将主要导航放在那里。

标准底部标签栏
<nav aria-label="Main" 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">
    
    <a href="#" aria-current="page" class="flex flex-col items-center justify-center gap-0.5
      text-indigo-600 min-w-[64px] min-h-[48px]">
      <svg class="w-6 h-6" fill="currentColor" aria-hidden="true"></svg>
      <span class="text-xs font-medium">Home</span>
    </a>
    
    <a href="#" class="flex flex-col items-center justify-center gap-0.5
      text-gray-500 min-w-[64px] min-h-[48px]">
      <svg class="w-6 h-6" fill="none" stroke="currentColor" aria-hidden="true"></svg>
      <span class="text-xs font-medium">Search</span>
    </a>
    
  </div>
</nav>
规则
  • 最多 5 个标签。3–4 个最理想。
  • 当前标签:实心图标 + 主色。非当前标签:线框图标 + 灰色。
  • 必须显示标签文字。仅使用图标的标签不易被用户发现。
  • 绝不要用汉堡菜单替代标签栏。
  • 在带刘海的设备上,需考虑底部安全区域。
安全区域 CSS
/* Only for elements with no bottom padding of their own */
.safe-area-bottom {
  padding-bottom: env(safe-area-inset-bottom);
}
/* Elements that already have padding: ADD the inset, don't replace the padding */
.pb-safe-4 {
  padding-bottom: calc(1rem + env(safe-area-inset-bottom));
}

还要为可滚动内容添加内边距(例如在 <main> 上使用 pb-[calc(4rem+env(safe-area-inset-bottom))]),避免最后一项被标签栏遮挡。


3. 适合手势操作的交互

滑动操作

<div class="relative overflow-hidden">
  
  <div class="absolute inset-y-0 right-0 flex items-center bg-red-600 px-6">
    <button type="button" class="text-white font-medium">Delete</button>
  </div>
  
  <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>
下拉刷新
  • 用户下拉时,在顶部显示指示器。
  • 使用旋转指示器或自定义动画。
  • 下拉距离约为 80px 时触发刷新。
  • 如可行,应提供触觉反馈(仅限原生应用)。
  • 在网页上,为滚动容器设置 overscroll-behavior-y: contain,以防浏览器自身也触发下拉刷新。
常见移动端手势
手势使用场景实现方式
向左/向右滑动显示操作、导航touch-action: pan-y
下拉刷新内容过度滚动检测
长按上下文菜单、重新排序pointerdown + 约 500ms 超时,在 pointermove/pointerup 时取消
捏合缩放图片/地图在可缩放元素上设置 touch-action: none + Pointer Events
向上滑动收起面板、展开底部面板上的拖动把手

在按钮和链接上设置 touch-action: manipulation 可消除双击缩放延迟,但不会启用自定义捏合处理。每种手势都必须提供一个可见的单击替代方式(按钮、菜单项)——WCAG 2.5.1 和可发现性都要求这样做。


4. iOS 与 Android 的设计语言

主要差异
元素iOS(Human Interface)Android(Material)
导航底部标签栏底部导航栏
返回从左侧边缘滑动/文本“Back”左上角箭头图标
标题可折叠的大标题居中或左对齐
按钮圆角矩形,无阴影圆角,带阴影
开关绿色/白色切换开关轨道 + 滑块,带涟漪效果
底部弹层顶部圆角,带拖动手柄全宽,带拖动手柄
字体SF Pro(系统字体)Roboto(系统字体)
间距16px 边距16px 边距
跨平台方案

同时面向两个平台构建时,精致度方面倾向采用 iOS 模式,交互反馈方面倾向采用 Material 模式。使用系统字体:

/* Use the design-context body font if set; otherwise the platform font */
font-family: var(--font-body, system-ui), -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

5. 安全区域

设备注意事项
/* 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" />

viewport-fit=cover 是必需的,否则 env(safe-area-inset-*) 返回的值将为零。切勿添加 maximum-scale=1 或 user-scalable=no,这会阻止双指缩放(WCAG 1.4.4)。

视口高度

显示移动浏览器工具栏时,100vh 会高于可见区域。全屏应用外壳和底部弹层使用 100dvh(会随工具栏变化),滚动时不应调整大小的首屏区域使用 100svh(Tailwind:h-dvh、h-svh)。


6. 移动端字体大小规范

推荐规范
角色大小字重行高
大标题34px7001.2
标题 128px7001.2
标题 222px7001.25
标题 320px6001.25
主标题17px6001.3
正文17px4001.5
提示文字16px4001.4
副标题15px4001.4
脚注13px4001.3
说明文字12px4001.3
规则
  • 为确保易读性,移动端正文最小字号为 16px。
  • 输入框、选择框和文本区域的字号必须 ≥16px——iOS Safari 会自动放大字号较小的字段。
  • 行长:最多 35–50 个字符,以便在移动设备上舒适阅读。
  • 使用基于 16px 根字号的 rem 单位。

7. 拇指触控区域优化

拇指触控区域示意图
+-----------------------------+
|     Hard to reach           |  <- Top 25%: Put secondary actions, titles
|                             |
|-----------------------------|
|     Comfortable stretch     |  <- Middle 50%: Content, scrollable lists
|                             |
|-----------------------------|
|     Easy / Natural          |  <- Bottom 25%: Primary actions, nav, FAB
+-----------------------------+
实用规则
  • 主要操作放在底部:CTA 按钮、提交按钮、导航。
  • 搜索栏:考虑放在底部(类似 iOS Safari)。
  • FAB(浮动操作按钮):放在右下角,尺寸为 56px,并带阴影。
  • 破坏性操作放在顶部:越难触及,就越难误触。

<div class="fixed bottom-0 inset-x-0 px-4 pt-12 pb-safe-4 bg-gradient-to-t from-white via-white
  to-transparent">
  <button type="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. 底部弹层/底部抽屉模式

底部弹层结构
<div class="fixed inset-0 z-50">
  
  <div class="absolute inset-0 bg-black/40 backdrop-blur-sm" data-dismiss></div>

  
  <div role="dialog" aria-modal="true" aria-labelledby="sheet-title"
    class="absolute bottom-0 inset-x-0 bg-white rounded-t-3xl
    max-h-[85dvh] overflow-y-auto overscroll-contain pb-safe-4">
    
    <div class="flex justify-center pt-3 pb-2" aria-hidden="true">
      <div class="w-10 h-1 rounded-full bg-gray-300"></div>
    </div>

    
    <div class="px-4 pb-6">
      <div class="flex items-center justify-between mb-4">
        <h2 id="sheet-title" class="text-xl font-bold text-gray-900">Sheet Title</h2>
        <button type="button" aria-label="Close" class="w-11 h-11 -mr-2 rounded-full
          flex items-center justify-center text-gray-500">✕</button>
      </div>
      
    </div>
  </div>
</div>
弹层变体
  • 预览弹层:显示 30% 的内容,拖动即可展开。
  • 操作弹层:选项列表(iOS 风格)。
  • 全屏弹层:向上滑动并覆盖整个屏幕,带关闭按钮。
  • 地图弹层:覆盖在地图上的常驻底部弹层(Google Maps 风格)。
弹层规则
  • 始终包含拖动手柄(宽 40px、高 4px、居中、圆角)。
  • 最大高度:视口的 85%。允许在内部滚动。
  • 关闭方式:向下滑动、点击背景或使用明确的关闭按钮。
  • 吸附位置:折叠、半展开、展开。

9. 移动端表单设计

规则
  1. 大尺寸输入框:最小高度为 48px,字号为 16px 及以上(避免 iOS 缩放)。
  2. 全宽输入框:在容器内从一侧边缘延伸到另一侧边缘。
  3. 智能键盘类型:使用 inputmode 属性。
  4. 固定提交按钮:固定在屏幕底部。
  5. 仅使用单列:移动端切勿并排放置字段。
Input Mode 属性

<input type="tel" inputmode="tel" />


<input type="email" inputmode="email" />


<input type="text" inputmode="numeric" pattern="[0-9]*" />


<input type="url" inputmode="url" />


<input type="search" inputmode="search" />
针对移动端优化的输入框
<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. 原生感动画

时间函数
:root {
  /* iOS-like spring curve (slight overshoot) */
  --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);
}
常见过渡效果
/* 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: transform 50ms ease, opacity 50ms ease;
}
移动端动画规则
  1. 动画时长控制在 400ms 以内。200–300ms 会显得灵敏。
  2. 仅使用 transform 和 opacity,以确保 60fps 性能。
  3. 对动画元素谨慎添加 will-change: transform。
  4. 遵循 prefers-reduced-motion:
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
  1. 为重要操作提供触觉反馈(仅原生应用)。

验证:渲染并检查

不要交付未经检查的代码。生成代码后:

  1. 在手机和桌面宽度下截图,例如运行 npx playwright screenshot --full-page --viewport-size=390,844 file://$PWD/index.html mobile.png,然后再用 --viewport-size=1440,900 截图(或使用开发服务器 URL)。
  2. 打开两张图片并检查:没有水平滚动,也没有文字被裁切或重叠;层级一目了然;已应用品牌设计令牌;图片按正确的宽高比加载。
  3. 用 Tab 键依次浏览一次:每个交互元素都显示可见的焦点环,顺序符合逻辑。
  4. 还要在 320px 宽度和横屏模式下截图;固定栏必须避开安全区域。无头浏览器不会模拟刘海,因此请在代码中确认每个固定的顶部/底部栏都添加了 env(safe-area-inset-*)(如果有 iOS Simulator,也可以在那里检查)。
  5. 修复发现的问题,并在报告完成前重新截图。

移动端设计检查清单

  • 所有点击目标均至少为 44×44px(Material 设计要求为 48×48),绝不低于 WCAG 的 24×24
  • 底部导航包含 3–5 个带标签的选项卡
  • 遵循安全区域要求(顶部、底部、两侧)
  • 正文至少为 16px(聚焦时不会触发 iOS 缩放)
  • 主要操作位于拇指易触达区域(底部)
  • 表单使用正确的 inputmode 属性
  • 底部弹层带有拖动把手和关闭手势
  • 动画时长低于 400ms,并使用 GPU 友好型属性
  • 已设置 viewport-fit=cover 元标签;未禁用缩放
  • 全高布局使用 dvh/svh,而非 100vh
  • 每种手势都有点击替代方式;底部弹层标记为对话框并进行焦点管理
  • 遵循 prefers-reduced-motion 设置
  • 内容在 320px 宽度下清晰易读
  • 所有屏幕均无水平滚动
  • 已在 320px、390px 和横屏模式下渲染并截图(参见“验证”)

评论

支持 Markdown