モバイル適応
目標
既存のインターフェースを、コア機能を削除せずにスマートフォンでうまく動作するように適応させます。ユーザーが他のターゲットを指定しない限り、iPhoneクラスのモバイルWebを優先します。
デフォルトターゲット
ユーザーがデバイスやブラウザを指定しない場合、以下の順に最適化します。
- ポートレートおよびランドスケープのiPhone Pro Maxクラス
- iOS Safari
- 幅
375-440 CSS pxのコンパクトタッチスクリーン - キーボード表示時、大きなテキスト、セーフエリア、動きの低減
調査すべきタイミング
このスキルは現在のプラットフォームの動作に依存します。
- ユーザーが最新/現在のガイダンス、iPhone固有の動作、Safari/WebKitの癖、セーフエリアの動作、PWA/ホーム画面の動作、または直接の引用を求めた場合は、公式ソースを閲覧してください。
- Apple Developer、WebKit、W3C/WCAG、MDN、Android Developers、web.dev を優先してください。
- 最近のプラットフォームの変更を引用する場合は、絶対日付を使用してください。
現在の高シグナルルールとソースについては、references/mobile-ui-2026.md をお読みください。
コアルール
-
コンパクトなスマートフォンはシングルペインに保つ。 ランドスケープのスマートフォンが一般的なブレークポイントを超えたからといって、デスクトップのIAに切り替えないでください。横向きに回転したスマートフォンでも、両手で腕を伸ばして持っています。ユーザーのメンタルモデルは「スマートフォン」であり、「タブレット」ではありません。マルチペインレイアウトに分割すると、どの要素も快適に使用できるほどの大きさがなく、混乱を招く体験になります。
-
真のトップレベルセクションには、ボトムファーストのモバイルナビゲーションのみを使用する。 3〜5個の主要な送り先に抑え、はみ出したものは「もっと見る」、シート、またはセカンダリフローに移動します。画面の下部は親指の自然な休息ゾーンです。プライマリナビをそこに配置することで、最も一般的なアクションに最も少ない労力でアクセスできるようになります。5個を超えるとタップターゲットが使いやすいサイズを下回り、スキャンが圧倒されます。
-
すべてのインタラクティブターゲットは、両方の寸法で少なくとも
44x44 CSS pxであること。 これには、見落とされがちな二次的な要素も含まれます。インラインアクションボタン(編集、削除、表示)、展開/折りたたみトグル、フィルターチップ、ツールバーのアイコンボタン、シートの閉じるボタン、チェックボックス/ラジオ行(<label>を入力単体ではなく完全なタップターゲットとして使用)。静電容量式タッチスクリーンは、指の接触パッチの中心を約44ptで登録します。ターゲットが小さいと、特に動きの中で誤タップのフラストレーションを引き起こします。不足しがちな一般的なTailwindクラス:h-8(32px)、h-9(36px)、アイコンのp-1(約24px)、p-1.5(約28px)、p-2(約32px)。すべてのタップ可能要素のベースラインとして、h-11(44px)、min-h-[44px]、または同等のものを使用してください。これはApple HIGに準拠し、WCAG 2.2の最小24pxを超えています。 -
ホバー、小さなアイコンのタップ、または非表示の行アクションに依存しないでください。 タッチにはホバー状態はありません。発見するためにホバーを必要とするものはすべて見えません。可視のコントロール、視覚的なヒントを伴うスワイプアクション、またはコンテキストシート/メニューを使用してください。
-
水平方向のページスクロールを避けてください。 片手でのスマートフォン操作は垂直方向の親指スクロールです。水平スクロールはユーザーの空間モデルを壊し、目に見えるアフォーダンスなしにコンテンツを画面外に隠します。ページ全体ではなく、テーブルやチャートをリフロー、スタック、ページネーション、またはローカルスクロールしてください。
-
viewport-fit=cover、env(safe-area-inset-*)、およびmin-height: 100dvhを使用してください。 最新のiPhoneは角が丸く、Dynamic Island、ホームインジケーターがあり、これらすべてが長方形のビューポートを侵食します。明示的なセーフエリア処理がないと、コンテンツがハードウェアのクロームの後ろにクリップされます。dvhは、古いvhでは対応していない折りたたみ可能なSafariツールバーを考慮します。 -
プライマリアクションはブラウザバー、ホームインジケーター、角の丸い部分、およびオンスクリーンキーボードから離して配置してください。 キーボードの後ろに隠れたり、ホームインジケーターと重なったりする「送信」ボタンは機能的に壊れています。ユーザーはそれを見ることができないか、システムジェスチャーをトリガーせずにタップすることができません。
-
フォームが多い、またはキーボードが多いフローでは、1つのメインスクロールコンテナを優先してください。 iOS Safariのネストされたスクロール領域は、スクロールトラッピングを引き起こします。ユーザーの親指が、ページをスクロールしようとしたときに内部コンテナをスクロールしたり、その逆を行ったりします。WebKitにはここに永続的なバグがあります(リファレンスファイルを参照)。ネストされたスクロールは、代替手段がない場合にのみ使用してください。
-
セマンティックなモバイル入力を使用してください。 フィールドの上にラベルを配置し(横ではありません。水平スペースがありません)、正しい
type、inputmode、autocomplete、enterkeyhintを使用してください。これらの属性は、どのキーボードが表示されるかを制御します。inputmode="decimal"は通貨用の数字パッドを表示し、enterkeyhint="next"を使用すると、ユーザーはキーボードを閉じずにフォームをタブ移動できます。 -
大きなテキストを実際のレイアウト入力として扱ってください。 iOSユーザーはシステム全体でより大きなテキストを設定でき、多くのユーザーが設定しています。ラップしてリフローしてください。重要な意味をトランケーションの後ろに隠さないでください。トランケートされたラベルによって、ユーザーが「普通預金口座」と「給与口座」のどちらを見ているのか推測しなければならない場合、レイアウトは失敗しています。
-
スマートフォンでは、チャートはストーリーを補助します。ストーリー全体ではありません。 スマートフォンの画面では、おそらく5〜6本の読み取り可能なバーまたは1つのドーナツグラフしかレンダリングできません。それでは、チャートが自己説明的であるのに十分なデータ密度ではありません。主要な数値とテキストの要約を先頭に配置し、チャートは視覚的な補強として使用してください。
-
ユーザーがより広範な再デザインを求めない限り、製品の既存のブランドとデザインシステムを維持してください。 モバイル適応とは、レイアウトとインタラクションに関するものであり、スキンを変更することではありません。
例
ナビゲーションシェル、データテーブル、または送信ボタンがあるフォームを変更する前に、references/mobile-examples.md をお読みください。サイドバーがボトムタブバーになる例、テーブルがスマートフォンでカードリストになる例、送信ボタンがキーボードの上に留まるフォームの例が、before/afterコードとともに記載されています。
ワークフロー
- ターゲットコンテキストをロックする。
- デバイス、ブラウザ、向き、使用コンテキスト
- 指定がない場合は、iPhone Pro Max + iOS Safariをデフォルトとする
- 最初にシェルを監査する。
- ナビゲーションモード
- セーフエリア
- スティッキー/固定バー
- ランドスケープ動作
- キーボード動作
- 各画面またはコンポーネントを監査する。
- リストと行
- フォーム
- テーブル
- チャート
- 空/エラー/ローディング状態
- ハードカットオーバーを選択する。
- 何をシングルカラムにするか
- 何をカードにするか
- 何をシート/ドロワーに移動するか
- 何を「もっと見る」の下のセカンダリにするか
- モバイルファーストの適応を実装する。
- コンポーネント内部にはコンテナクエリを優先する
- シェル/レイアウトモードの変更にはビューポートクエリを優先する
- 明示的に要求されない限り、古い半分デスクトップ/半分モバイルの動作を維持しない
- コンパクトなポートレートとコンパクトなランドスケープで検証する。
- 最初にSafari/WebKit
- 次にChromium
- 最初に最もリスクの高い問題を報告し、次に具体的な変更点と残っているギャップを報告する。
画面チェックリスト
シェルとナビゲーション
- ランドスケープのスマートフォンをスマートフォンシェルに保つ。
- 依然としてスマートフォンであるデバイスに対して、ハードな
md => デスクトップサイドバーの切り替えを避ける。 - 下部UIに
env(safe-area-inset-bottom)でパディングを追加する。 - スティッキーアクションをボトムナビの上に配置する。
- モバイルラベルを短く保つ。
リストと行
- タイトル、メタデータ、金額が必要に応じて2行に折り返せるようにする。
- 価格、残高、合計のための安定したスペースを確保する。
- 詰め込まれたインラインメタデータよりも、積み重ねられたメタデータを優先する。
- ホバーではなく、可視のコントロールまたはシート/メニューでアクションを公開する。
- 行のアクションボタン(編集、削除、表示、展開)のサイズを少なくとも
44x44 CSS pxにする — プライマリナビやツールバーボタンだけではありません。
フォーム
- コンパクトなスマートフォンでは1カラムを使用する。
- 送信ボタンをキーボードの上に表示したままにする。
- 明確な全幅のプライマリCTAを使用する。
- 長いフローはステップまたはプログレッシブディスクロージャーに分割する。
- フォーマットや精度が重要な場合は、通貨に
type="number"を使用しない。
テーブルとインポート/レビューフロー
- 密度の高い編集可能なテーブルをスマートフォンではカード/リストに変換する。
- 真のテーブルを維持する必要がある場合は、水平スクロールをテーブルにのみ分離する。
- スティッキーヘッダーやツールバーがフォーカスされた入力を隠さないようにする。
チャートと統計
- 主要な数値と短い説明を先頭に配置する。
- コンパクトな凡例とテキストフォールバックを追加する。
- 読みにくい密集したバーよりも、水平スクロールまたはページ比較を優先する。
- コンパクト画面での小さな円/ドーナツグラフを避ける。
検証
以下の各チェックについて、特定の合格条件を確認し、推奨されるツールを使用してください。実機テストがゴールドスタンダードです。シミュレーターは反復作業には有用ですが、キーボードのタイミング、スクロールの慣性、タップの精度を完全に再現することはできません。
-
ポートレートとランドスケープ — スマートフォンは両方の向きでモバイルシェルのままである。レイアウトの破損、コンテンツのオーバーフロー、デスクトップのサイドバーやマルチペインビューへの突然の切り替えがないこと。375px(iPhone SE/miniクラス)、390px(iPhone Pro)、430px(iPhone Pro Max)のポートレートと、それらのランドスケープ相当でテストする。Chrome DevToolsのデバイスツールバーまたはXcode Simulatorを使用する。
-
iOS Safariのセーフエリア — コンテンツがDynamic Island、角の丸い部分、またはホームインジケーターによってクリップされていないこと。下部に固定された要素には、可視の
env(safe-area-inset-bottom)パディング(Face ID搭載iPhoneでは約34px)があること。ビューポートメタタグにviewport-fit=coverが設定されていることを確認する。これがないと、すべてのenv(safe-area-inset-*)値は0を返す。Xcode Simulator(デバイスごとに正確なインセット)またはPolypane 26以上(実際のセーフエリアインセットプリセットを備えたデスクトップブラウザ)でテストするのが最適。Chrome DevTools 135以上はEmulation.setSafeAreaInsetsOverrideをサポートしているが、手動設定が必要。 -
キーボード表示時のフォームフロー — 各入力を順にフォーカスし、以下を確認する。(1) フォーカスされたフィールドがビューにスクロールする、(2) 送信アクションが表示されタップ可能である、(3) スティッキーヘッダーがフォーカスされたフィールドを隠さない。
position: fixed; bottom: 0の要素はiOSキーボードの後ろに隠れる(Layout Viewportは縮小しない)ことに注意。position: sticky; bottom: 0もキーボード表示中にピン留めできない(WebKitバグ #202120)。PlaywrightとCypressは実際のオンスクリーンキーボードをトリガーできない。これには実機テストまたはSafari Web Inspectorを備えたXcode Simulatorが必要。 -
大きなテキスト / 表示ズーム — WCAG 1.4.4(AA)では、コンテンツを失うことなくテキストを200%に拡大できることが求められる。WCAG 1.4.10(AA)では、水平スクロールなしで400%のズーム(320px幅のビューポートに相当)でリフローできることが求められる。テスト方法:(1) ブラウザのズームを200%に設定し、トランケーションや重なりがないことを確認する、(2) ビューポートを1280pxに設定し、400%にズームして320pxのリフロー要件をシミュレートする、(3) iOSの設定 > アクセシビリティ > 画面表示とテキストサイズ > さらに大きな文字を最大で有効にする。ビューポートメタタグが
user-scalable=noを設定したり、maximum-scaleを2.0未満に設定したりしていないことを確認する。 -
動きの低減 — アニメーションが
prefers-reduced-motion: reduceを尊重すること。トランジションは状態変化を伝えるが、動きではなくクロスフェードや不透明度を使用する。iOS Safariは、Reduce Motionがオンの場合でもWebアニメーションを自動的に抑制しない。開発者が処理する必要がある。テスト方法:Chrome DevToolsのRenderingタブ > "Emulate prefers-reduced-motion"、Safari Web Inspectorの環境設定オーバーライド(2022年後半以降利用可能)、またはPlaywrightのpage.emulateMedia({ reducedMotion: 'reduce' })。 -
空/エラー/ローディング状態 — これらの状態がコンパクト画面で適切にレンダリングされること。ローディングスケルトンはモバイルレイアウトに一致し、デスクトップのものではないこと。エラーメッセージはスクロールなしで読めること。
-
スタンドアロン/PWAモード(関連する場合) — アプリが
display: standaloneをサポートしている場合、ステータスバー領域、ホームインジケーター、ジェスチャー領域が処理されていることを確認する。svhとdvhはスタンドアロンモードでは同じ値に解決される(折りたたみ可能なツールバーがないため)(WebKitバグ #261185)。WebKitバグ #254868 は不正確な高さの値を引き起こす可能性がある。WebKitバグ #265578 は、Safari UIがビューにアニメーションで戻るときにビジュアルビューポートの高さの更新が遅れる原因となる。 -
水平方向のドキュメントスクロールがない — ページ本文を左右にスワイプしても動きがないこと。水平スクロールは特定のコンテナ(テーブル、カルーセル)に分離され、可視のオーバーフローアフォーダンスと、Safari UIのシフトを防ぐための
overscroll-behavior: containがあること(WebKitバグ #240861)。Playwrightでの自動検証の場合:const hasOverflow = await page.evaluate(() => document.documentElement.scrollWidth > document.documentElement.clientWidth ); expect(hasOverflow).toBe(false);
成果物
このスキルを使用する場合、以下を作成すること。
- 短いモバイル適応計画
- 最初に最もリスクの高い問題
- 画面ごとの具体的な変更
- 実行された検証
- 残っているデバイス/ブラウザの不確実性