mcpField
M
mobile-ui-design

mobile-ui-design

github.com/arnavpuriデザイン・UI17114 回インストール4 週間前に更新
リポジトリ

mobile-ui-design について

モバイル画面を構築するエージェント向けのデザインスキルです。タッチ操作、ナビゲーション、安全領域、フォーム、モーション、アクセシビリティ、画面確認を扱い、iOSとAndroidの設計パターンを案内します。

主な機能

  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 変数を確認します。何もない場合は、デフォルト(Primary #2563EB、Secondary #7C3AED、Accent #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: 同じ変数を(v3 の theme.extend、v4 の @theme で)primary、primary-light、primary-dark、secondary、accent、neutral-*、font-heading、font-body として公開します。以下の例にある indigo-* / gray-* クラスは、これらのトークンを表すプレースホルダーです。
  4. Figma: ユーザーが Figma の URL を提示した場合は、Figma MCP(get_design_context、get_screenshot)を使って取得し、それに合わせます。そのデザインでは、デザインコンテキストファイルより優先されます。
  5. ネイティブアプリ(React Native/Flutter:CSS 変数ではなくテーマオブジェクトにトークンを対応付け)、PWA、レスポンシブ Web サイトのどれにするかを尋ねます。

1. タッチターゲットのサイズ

すべてのインタラクティブ要素は、確実にタップできる大きさにする必要があります。

最小サイズ
ソース最小ターゲット備考
Apple HIG44×44ptWeb では 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×48)にします。

実装
/* 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 引っ張った時点で更新を開始します。
  • 可能であれば、触覚フィードバックを提供します(ネイティブのみ)。
  • Web では、スクローラーに 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(ヒューマンインターフェース)Android(Material)
ナビゲーション画面下部のタブバー下部ナビゲーションバー
戻る操作左端からのスワイプ/「戻る」というテキスト左上の矢印アイコン
タイトルスクロール時に折りたたまれる大きなタイトル中央揃えまたは左揃え
ボタン角丸の長方形、浮き上がりなし角丸、浮き上がりあり
スイッチ緑/白のトグルリップル効果付きのトラックとつまみ
シート上部が角丸、ドラッグハンドル付き全幅、ドラッグハンドル付き
タイポグラフィ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);
}
ビューポートのメタ設定
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />

env(safe-area-inset-*) がゼロ以外の値を返すには、viewport-fit=cover が必要です。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. 1 列のみ:モバイルではフィールドを横並びにしないでください。
入力モード属性

<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. 60fps のパフォーマンスを保つため、transform と opacity のみを使用します。
  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シミュレーターで確認します)。
  5. 見つかった問題を修正し、完了を報告する前にもう一度スクリーンショットを撮影します。

モバイルデザインチェックリスト

  • すべてのタップ対象が44×44px以上(Materialでは48×48px)。WCAGの24×24pxを下回らないこと
  • ラベル付きのタブが3~5個ある下部ナビゲーション
  • セーフエリア(上部、下部、左右)に対応していること
  • 本文テキストが16px以上(フォーカス時にiOSでズームされないこと)
  • 主な操作を親指の届く範囲(下部)に配置すること
  • フォームで正しいinputmode属性を使うこと
  • シートにドラッグハンドルと閉じるジェスチャーを用意すること
  • アニメーションを400ms未満にし、GPUに適したプロパティを使うこと
  • viewport-fit=coverメタタグを設定し、ズームを無効にしないこと
  • 高さ全体を使うレイアウトでは100vhではなくdvh/svhを使うこと
  • すべてのジェスチャーにタップ操作の代替手段を用意すること。シートにはダイアログのラベルを付け、フォーカスを管理すること
  • prefers-reduced-motionに対応すること
  • コンテンツが幅320pxで読み取れること
  • どの画面でも横スクロールが発生しないこと
  • 320px、390px、横向きでレンダリングしてスクリーンショットを撮影すること(「検証」を参照)

コメント