性能优化
移动端触控优先 UX 设计与实现:需要触控目标、无…
在移动端 Web、iOS、Android 等触控优先界面中,按平台规范设计可点击区域、布局、手势与性能,避免 hover 依赖和不适配问题。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
移动端触控优先 UX 设计与实现:需要触通用
解决思路
- 版本敏感:每个 API 名称、SDK gate 和浏览器支持结论都曾在 2026-09-08 对照原始来源验证;先查 _jutsu/VERSIONS.md,若日期过旧,使用版本号前重新验证。
- Apple iOS/iPadOS 触控目标:按 44x44 pt 设计,硬下限 28x28 pt;带 bezel 控件周围留约 12 pt padding,不带 bezel 控件周围留约 24 pt;参考 Apple HIG, Accessibility > Mobility。
- Apple watchOS 触控目标:按 44x44 pt 设计,硬下限 28x28 pt,间距同 iOS/iPadOS 规则。
- Android 触控目标:按 48x48 dp 设计,硬下限 48x48 dp,目标之间留 8 dp;参考 Material Design 3。
- Web mobile 触控目标:按 44x44 CSS px 设计,硬下限 24x24 CSS px;目标间 24 px 未重叠间距可满足 WCAG AA 例外;WCAG 2.5.5 Target Size (Enhanced) AAA = 44x44,WCAG 2.5.8 Target Size (Minimum) AA = 24x24。
- 触控目标通用规则:任何小于平台最小值的 tap target 都是 usability bug;命中区域可超出可见 glyph,用 padding、hitSlop 或透明 inner spacer 扩展,但 interactive surface 必须达到最小值;spacing 与 size 同等重要,两个 44pt 按钮边缘相接仍易误触。
- 无 hover 原则:不要将 :hover 作为主要触发或唯一揭示方式;触屏没有 hover,移动端仅 hover 可达的 affordance 等于消失;默认可见,hover 样式只作为桌面 enhancement,不能承载交互。
- CSS 实现无 hover:默认保持元素可见;把 hover 样式放入 @media (hover: hover) and (pointer: fine) 中,例如 .card { opacity: 1; transform: translateY(0); },在媒体查询内才写 .card { opacity: 0.85; } 和 .card:hover { opacity: 1; transform: translateY(-2px); }。
- SwiftUI 实现无 hover:用 .onTapGesture 处理点击,用 .contextMenu 处理长按菜单,不要使用伪 hover。
- Compose 实现无 hover:用 Modifier.combinedClickable(onClick = ..., onLongClick = ...) 同时处理点击和长按上下文菜单。
- Thumb Zones:竖屏手机使用以单手或 cradled 为主,拇指从底部角落旋转;屏幕分为 bottom third EASY、middle OK、top HARD。
- Thumb Zones 布局:bottom third(EASY)放 primary CTA、send、confirm、FAB、tab bar。
- Thumb Zones 布局:middle(OK)放 content 和 secondary actions。
- Thumb Zones 布局:top(HARD)放 back、close、search、profile 等用户预期去够而不是反射点击的元素。
- Thumb Zones 规则:primary CTA 放 bottom half;secondary、低频或 destructive actions 放 top;不要把 Pay 按钮放在手机屏幕右上角。
- Safe Areas Web:在 viewport meta 中使用 viewport-fit=cover,并通过 env(safe-area-inset-top|right|bottom|left) 尊重 notch 和 home indicator。
- Safe Areas Web fixed 元素:例如 .fab 用 position: fixed; bottom: calc(env(safe-area-inset-bottom) + 16px); right: calc(env(safe-area-inset-right) + 16px);。
- Safe Areas SwiftUI:用 .safeAreaInset(edge: ...) 和 safeAreaInsets env 尊重 nav bar、tab bar、notch、home。
- Safe Areas Compose:用 Modifier.windowInsetsPadding(WindowInsets.safeDrawing) 尊重 system bars、IME、cutouts。
- Reduced Motion Web CSS:用 @media (prefers-reduced-motion: reduce) 提供减少动画样式。
- Reduced Motion Web JS:用 window.matchMedia('(prefers-reduced-motion: reduce)') 检测并切换动画逻辑。
- Reduced Motion SwiftUI:用 @Environment(\.accessibilityReduceMotion) var reduceMotion;在 offset 和 animation 中根据 reduceMotion 选择 0 或 .none,正常时用 .easeOut(duration: 0.3)。
- Reduced Motion UIKit:用 UIAccessibility.isReduceMotionEnabled;动画 duration 设为 enabled ? 0 : 0.3,再执行 UIView.animate。
- Reduced Motion Compose:写 helper 读取 Settings.Global.ANIMATOR_DURATION_SCALE == 0f;优先用 ValueAnimator.areAnimatorsEnabled()(API 26+),因为它覆盖 developer-options Animation off、Battery Saver 和 Settings -> Accessibility 的 Remove animations;动画 spec 用 snap() 或 tween<Float>(durationMillis = 300)。
- 手势 Swipe-back:iOS 从 leading edge 边缘滑动 pop navigation stack;不要覆盖;Android 用 predictive back 镜像,Android 13 (API 33) 起可用,通过 android:enableOnBackInvokedCallback="true" 加 OnBackPressedCallback 或 PredictiveBackHandler 选择启用;Android 15 起 opted-in app 自动显示系统 back-to-home、cross-activity、cross-task 动画。
- 手势 Pull-to-refresh:在 scroll surface 顶部向下拖拽重新请求数据,适用于 feeds、mail、lists。
- 手势 Drag-to-dismiss:modal sheets 和 image viewers 向下拖过阈值后关闭,阈值通常 100-150pt。
- 手势 Pinch-to-zoom:在图片、地图和可缩放画布上用双指 spread/pinch 缩放,并遵守 minimum/maximum scale。
- 手势 Swipe actions on rows:在列表行上水平滑动显示 contextual actions,如 delete、archive、mark read;leading 与 trailing swipe 对应不同 action sets。
- 性能预算 Cold start:mid-range devices 上 <2s;基线用 Android Pixel 4a、iPhone SE (2nd gen);如果在 Pixel 4a 上 4s,在用户实际持有的 low-end device 上可能 8s。
- 性能预算 Frame budget:60fps 每帧 16.67ms,120fps 每帧 8.33ms(ProMotion / high-refresh Android);主线程上任何同步操作超过该值都会造成 jank。
- 性能预算 Binary size:加入重型媒体库前目标 <30MB APK 和 <50MB IPA;Lottie/Rive 会增加 500KB 到 2MB;检查 asset folders,常见问题是 PNG 未换成 WebP 或 vector。
- 性能预算 Battery:后台不要持续 CPU 活动;合并工作,使用平台 scheduler,Android 用 WorkManager,iOS 用 BGTaskScheduler;除非用户明确要求前台媒体,避免 wake-locks。
- 性能预算 Network:尊重连接提示;Web 用 Save-Data request header 和 navigator.connection.saveData;iOS 用 URLSessionConfiguration.allowsCellularAccess 和 NWPathMonitor 区分 cellular 与 Wi-Fi;Android 用 ConnectivityManager + NetworkCapabilities 检测 metered networks。
- 反模式检查 1:不要把 hover 作为唯一 reveal;BAD 是 .card .actions { opacity: 0; } 后只有 .card:hover .actions { opacity: 1; };GOOD 是 .card .actions { opacity: 1; },再在 @media (hover: hover) and (pointer: fine) 内加 hover 增强。
- 反模式检查 2:不要 sub-minimum touch targets;BAD 是 IconButton modifier = Modifier.size(32.dp),虽然 Material 3 的 IconButton 可能通过 minimumInteractiveComponentSize() 自救,但自定义 Box 或 Row 用同样 modifier 时 target 真的只有 32dp;GOOD 是外层 Modifier.size(48.dp),内部 Icon modifier = Modifier.size(24.dp)。
- 反模式检查 3:不要忽略 safe area insets;BAD 是底部 CTA 放在 VStack 的 Spacer 后,会落到现代 iPhone home indicator 下面;GOOD 是用 ScrollView { content }.safeAreaInset(edge: .bottom) 包裹底部 CTA。
- 按需加载子技能:手势深挖加载 references/gestures-deep.md;移动 a11y 深挖加载 references/accessibility-mobile.md;Compose 专属动画加载 ../compose-motion/SKILL.md;SwiftUI 专属动画加载 ../swiftui-motion/SKILL.md。
适用边界 · 注意事项
- 纯桌面端、非触屏或没有移动端容器的项目,不必强制应用移动触控目标、thumb zone、safe area 和 no-hover 规则。
- 已有严格平台设计系统且组件已内建这些约束时,不要重复实现;但仍应检查自定义组件是否绕过 minimum target、safe area 或 reduced motion。
- 如果产品目标只是桌面专业工具且明确无移动需求,hover-only 交互可以作为主要交互;一旦需要移动 Web 或 App,则必须按本技能改造。