# モバイルと間隔に関するベストプラクティス

モバイルデバイスで効果的なインタラクティブスペースを作成するには、タッチ操作、間隔、パフォーマンスを慎重に考慮する必要があります。本ガイドはモバイル最適化のための重要な実践事項を扱います。

## 🎯 モバイルファースト設計の原則

### タッチターゲットのガイドライン

インタラクティブ要素はタッチスクリーン上でアクセスしやすく使いやすい必要があります：

#### 最小サイズ

* **インタラクティブポイント**: 最小 44px × 44px（Apple の推奨）
* **ボタンと CTA**: 最小 48px × 48px（Google の推奨）
* **ターゲット間の間隔**: 最小 8px の間隔

#### 快適なサイズ

* **最適なタッチターゲット**: 56px × 56px 以上
* **十分な余白**: インタラクティブ要素間は 16px 以上
* **親指に優しいゾーン**: 主要なアクションを届きやすい位置に配置する

### 小さい画面での視覚的階層

```css
/* モバイル最適化されたインタラクティブポイント */
@media (max-width: 768px) {
  .interactive-point {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    box-shadow: 0 2px 8px rgba(0,0,0,0.2);
  }
  
  .interactive-point + .interactive-point {
    margin-left: 16px;
  }
}
```

## 📐 間隔戦略

### グリッドベースの間隔システム

インタラクティブスペース全体で一貫した間隔を確立します：

#### ベースユニットシステム

* **4px のベースユニット**: すべての間隔は 4px の倍数にする
* **小さい間隔**: 8px（2ユニット）
* **中程度の間隔**: 16px（4ユニット）
* **大きい間隔**: 24px（6ユニット）
* **特大**: 32px（8ユニット）

#### レスポンシブな間隔調整

```css
.interactive-container {
  /* デスクトップの間隔 */
  padding: 32px;
  gap: 24px;
}

@media (max-width: 768px) {
  .interactive-container {
    /* モバイルの間隔 - 小さい画面では縮小 */
    padding: 16px;
    gap: 16px;
  }
}

@media (max-width: 480px) {
  .interactive-container {
    /* 小型モバイル - 最小限の間隔 */
    padding: 12px;
    gap: 12px;
  }
}
```

### コンテンツ間隔のガイドライン

#### インタラクティブポイントの配置

* **最小距離**: ポイント中心間 44px
* **推奨距離**: 快適な操作のため 60px 以上
* **端のマージン**: 画面端から最低 24px
* **クラスタ回避**: 近接して 3 点以上配置しない

#### テキストとコンテンツの間隔

* **行間（ラインハイト）**: 読みやすさのため 1.4〜1.6
* **段落間隔**: 段落間 16px
* **見出しの間隔**: 上 24px、下 16px
* **ボタン間の間隔**: 周囲の要素から最低 16px

## 🚀 パフォーマンス最適化

### モバイル向け画像最適化

```css
/* 最適化された読み込みを伴うレスポンシブ画像 */
.interactive-background {
  background-image: url('mobile-background-small.jpg');
}

@media (min-width: 768px) {
  .interactive-background {
    background-image: url('tablet-background-medium.jpg');
  }
}

@media (min-width: 1200px) {
  .interactive-background {
    background-image: url('desktop-background-large.jpg');
  }
}
```

### 遅延読み込みの実装

* **ファーストビュー（上部表示領域）**: すぐに表示されるコンテンツを先に読み込む
* **段階的読み込み（プログレッシブ）**: ユーザーのスクロールに応じて追加コンテンツを読み込む
* **プレースホルダー画像**: 読み込み中は低品質のプレースホルダーを表示する
* **リソース優先度設定**: まず重要な CSS と JavaScript を読み込む

### アニメーションのパフォーマンス

```css
/* GPU 加速のアニメーション */
.interactive-point {
  will-change: transform;
  transform: translateZ(0); /* GPU 加速を強制 */
}

.interactive-point:hover {
  transform: scale(1.1) translateZ(0);
  transition: transform 0.2s ease; /* 短くキビキビしたトランジション */
}

/* 動きを抑えたいユーザー向けの設定 */
@media (prefers-reduced-motion: reduce) {
  .interactive-point {
    transition: none;
  }
}
```

## 📱 モバイルのインタラクションパターン

### タッチジェスチャーのサポート

```javascript
// 強化されたタッチインタラクション処理
class InteractiveTouch {
  constructor(element) {
    this.element = element;
    this.startTime = 0;
    this.isLongPress = false;
    
    this.bindEvents();
  }
  
  bindEvents() {
    this.element.addEventListener('touchstart', this.handleTouchStart.bind(this));
    this.element.addEventListener('touchend', this.handleTouchEnd.bind(this));
    this.element.addEventListener('touchmove', this.handleTouchMove.bind(this));
  }
  
  handleTouchStart(e) {
    this.startTime = Date.now();
    this.startX = e.touches[0].clientX;
    this.startY = e.touches[0].clientY;
    
    // 長押し検出
    this.longPressTimer = setTimeout(() => {
      this.isLongPress = true;
      this.showContextMenu();
    }, 500);
  }
  
  handleTouchEnd(e) {
    clearTimeout(this.longPressTimer);
    
    const duration = Date.now() - this.startTime;
    
    if (duration < 500 && !this.isLongPress) {
      // クイックタップ - 製品情報を表示
      this.showProductInfo();
    }
    
    this.isLongPress = false;
  }
}
```

### スワイプナビゲーション

* **横方向のスワイプ**: インタラクティブスペース間を移動
* **縦方向のスワイプ**: 通常どおりコンテンツをスクロール
* **ピンチジェスチャー**: インタラクティブ領域をズーム（該当する場合）
* **ダブルタップ**: クイックアクションのショートカット

## 🎨 モバイル向けビジュアルデザイン

### タイポグラフィのスケーリング

```css
/* レスポンシブタイポグラフィ */
.interactive-content {
  font-size: 16px; /* モバイルの読みやすさの基本サイズ */
  line-height: 1.5;
}

.interactive-title {
  font-size: 24px;
  font-weight: 600;
  margin-bottom: 12px;
}

.interactive-description {
  font-size: 14px;
  color: #666;
  line-height: 1.4;
}

@media (max-width: 480px) {
  .interactive-title {
    font-size: 20px; /* 小さい画面ではやや小さめ */
  }
  
  .interactive-description {
    font-size: 13px;
  }
}
```

### 色とコントラスト

* **高コントラスト**: テキストは最低 4.5:1 の比率を確保する
* **タッチフィードバック**: インタラクションの視覚的確認
* **ブランドの一貫性**: 画面サイズに関係なくブランドカラーを維持する
* **ダークモード対応**: 代替カラースキームを検討する

### 視覚的フィードバックシステム

```css
/* タッチフィードバックのアニメーション */
.interactive-point {
  position: relative;
  overflow: hidden;
}

.interactive-point::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.3);
  transform: translate(-50%, -50%);
  transition: width 0.6s, height 0.6s;
}

.interactive-point:active::after {
  width: 200px;
  height: 200px;
}
```

## 🔧 技術的実装

### プログレッシブエンハンスメント

基本的な体験から始め、対応可能なデバイス向けに拡張します：

#### ベース体験（すべてのデバイス）

* 基本的なリンク付きの静的画像
* 必須の製品情報
* シンプルなナビゲーション

#### 強化された体験（最新のモバイル）

* アニメーションを持つインタラクティブポイント
* タッチジェスチャー
* 高度な視覚効果

#### フル体験（ハイエンドデバイス）

* 複雑なアニメーション
* リアルタイムエフェクト
* 高度なインタラクション

### レスポンシブのブレークポイント

```css
/* モバイルファーストのレスポンシブデザイン */
.interactive-space {
  /* モバイルの基本スタイル */
  padding: 16px;
}

/* 大型のモバイルフォン */
@media (min-width: 480px) {
  .interactive-space {
    padding: 20px;
  }
}

/* タブレット */
@media (min-width: 768px) {
  .interactive-space {
    padding: 24px;
  }
}

/* デスクトップ */
@media (min-width: 1024px) {
  .interactive-space {
    padding: 32px;
  }
}
```

## ⚡ バッテリーとパフォーマンスの考慮事項

### CPU 集中型の操作

* **同時アニメーションを制限する**: 最大 3〜4 の同時アニメーション
* **CSS トランスフォームを使用する**: レイアウトプロパティを変更するより効率的
* **スクロールイベントを間引く（スロットル）**: イベントハンドラの頻度を制限する
* **Intersection Observer を実装する**: 表示されている要素のみアニメーションする

### メモリ管理

```javascript
// 効率的なメモリ使用
class InteractiveManager {
  constructor() {
    this.activeInteractions = new Map();
    this.intersectionObserver = new IntersectionObserver(
      this.handleIntersection.bind(this),
      { threshold: 0.1 }
    );
  }
  
  handleIntersection(entries) {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        this.activateInteraction(entry.target);
      } else {
        this.deactivateInteraction(entry.target);
      }
    });
  }
  
  activateInteraction(element) {
    // 表示されているときのみインタラクティブ機能を読み込む
    if (!this.activeInteractions.has(element)) {
      const interaction = new InteractivePoint(element);
      this.activeInteractions.set(element, interaction);
    }
  }
  
  deactivateInteraction(element) {
    // 表示外になったらクリーンアップする
    const interaction = this.activeInteractions.get(element);
    if (interaction) {
      interaction.destroy();
      this.activeInteractions.delete(element);
    }
  }
}
```

## 🧪 テストと品質保証

### デバイステストマトリクス

* **iOS**: iPhone SE、iPhone 12、iPhone 14 Pro、iPad、iPad Pro
* **Android**: 低価格デバイス（Samsung Aシリーズ）、フラグシップ（Pixel、Samsung Sシリーズ）
* **画面サイズ**: 幅 320px〜428px（モバイル）、768px+（タブレット）

### パフォーマンステストツール

* **Lighthouse**: Core Web Vitals とパフォーマンススコア
* **WebPageTest**: 実世界のパフォーマンス指標
* **Chrome DevTools**: モバイルのシミュレーションとパフォーマンスプロファイリング
* **実機テスト**: 実際のハードウェアでのテスト

### アクセシビリティテスト

```javascript
// アクセシビリティ機能
function enhanceAccessibility() {
  // 適切な ARIA ラベルを追加する
  document.querySelectorAll('.interactive-point').forEach(point => {
    point.setAttribute('role', 'button');
    point.setAttribute('aria-label', '製品の詳細を表示');
    point.setAttribute('tabindex', '0');
    
    // キーボードサポート
    point.addEventListener('keydown', (e) => {
      if (e.key === 'Enter' || e.key === ' ') {
        e.preventDefault();
        point.click();
      }
    });
  });
}
```

## 📊 分析と最適化

### モバイル固有の指標

* **タッチの精度**: ポイント操作の成功率
* **エンゲージメントの深さ**: インタラクティブ要素で費やされた時間
* **コンバージョン率**: モバイル対デスクトップのパフォーマンス比較
* **ユーザーフロー分析**: インタラクティブ体験におけるパス

### A/B テストの注力領域

* **ポイントサイズ**: 44px 対 56px 対 64px
* **間隔のバリエーション**: タイト（狭い）対 十分な余白
* **アニメーション速度**: 速い対 遅いトランジション
* **コンテンツ密度**: 画面ごとの情報量

### ユーザーフィードバックの収集

```javascript
// 簡単なフィードバック収集
function collectMobileFeedback() {
  const feedback = {
    device: navigator.userAgent,
    screenSize: `${window.innerWidth}x${window.innerHeight}`,
    touchSupport: 'ontouchstart' in window,
    interactionTime: Date.now() - startTime,
    completedInteractions: interactionCount
  };
  
  // 分析に送信
  analytics.track('mobile_interaction_complete', feedback);
}
```

## 💡 高度なモバイル機能

### プログレッシブウェブアプリの機能

* **ホーム画面に追加**: カスタムのアプリライクな体験
* **オフラインサポート**: 重要なインタラクティブコンテンツをキャッシュする
* **プッシュ通知**: 更新でユーザーを惹きつける
* **バックグラウンド同期**: 接続が復帰したときにコンテンツを更新する

### デバイス固有の強化

* **ハプティックフィードバック**: インタラクション時の振動（対応している場合）
* **カメラ連携**: AR 試着体験
* **位置情報**: 位置ベースのインタラクティブコンテンツ
* **音声コマンド**: ハンズフリーのナビゲーションオプション

この包括的なモバイル最適化により、インタラクティブスペースはすべてのデバイスで優れたユーザー体験を提供し、パフォーマンスとアクセシビリティの基準を維持します。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.openspaces.design/english-ja/plain-jane-interactive/sections-and-features/best-practices-for-mobile-+-spacing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
