レスポンシブガイドライン

RoomCraft — v1.0.0 — 2026-03-19

Responsive Guidelines: RoomCraft

作成日: 2026-03-19 アプローチ: モバイルファースト(min-width 方式) 対象: 一般ユーザー向けサービス + メーカー管理画面


1. ブレークポイント定義

名前対象デバイスTailwind プレフィックス
base375px+スマートフォン (標準)(なし)
sm640px+大型スマートフォンsm:
md768px+タブレットmd:
lg1024px+デスクトップlg:
xl1280px+大型デスクトップxl:
2xl1536px+超大型ディスプレイ2xl:

tailwind.config.ts 設定

import type { Config } from 'tailwindcss'

const config: Config = {
  theme: {
    extend: {
      screens: {
        // Tailwind デフォルトと同値(確認用)
        'sm':  '640px',
        'md':  '768px',
        'lg':  '1024px',
        'xl':  '1280px',
        '2xl': '1536px',
      },
    },
  },
}

2. Safe Area 対応

2.1 必須対応箇所

要素対応方法
BottomSheetpadding-bottom: env(safe-area-inset-bottom)
固定フッターpadding-bottom: env(safe-area-inset-bottom)
固定ヘッダーpadding-top: env(safe-area-inset-top)
サイドメニュー(左)padding-left: env(safe-area-inset-left)

2.2 Tailwind プラグイン設定

// tailwind.config.ts
plugins: [
  plugin(function ({ addUtilities }) {
    addUtilities({
      '.safe-top':    { paddingTop:    'env(safe-area-inset-top)' },
      '.safe-bottom': { paddingBottom: 'env(safe-area-inset-bottom)' },
      '.safe-left':   { paddingLeft:   'env(safe-area-inset-left)' },
      '.safe-right':  { paddingRight:  'env(safe-area-inset-right)' },
    })
  }),
],
// 使用例
<footer className="fixed bottom-0 left-0 right-0 safe-bottom bg-white">
  ...
</footer>

3. タッチターゲット

最小サイズ: 44px × 44px(Apple HIG / WCAG 準拠)

// ボタン
<Button className="min-h-[44px] min-w-[44px]">...</Button>

// アイコンボタン
<button className="flex items-center justify-center w-11 h-11 rounded-full">
  <Icon size={20} />
</button>

// リストアイテム
<li className="min-h-[44px] flex items-center px-4">...</li>

4. 3Dビューポートのレスポンシブ設計

4.1 レイアウト仕様

モバイル (base / sm: ~767px)

┌────────────────────────────┐ │ ヘッダー (fixed, safe-top) │ 高さ: 56px ├────────────────────────────┤ │ │ │ │ │ 3Dビューポート │ h-[calc(100dvh-56px-200px)] │ (全画面) │ │ │ │ │ ├────────────────────────────┤ │ BottomSheet (家具パネル) │ 高さ: 200px (折りたたみ時) │ ドラッグで展開可能 │ 高さ: 60dvh (展開時) └────────────────────────────┘ ← safe-bottom
// モバイル 3Dビューポート
<div className="
  h-[calc(100dvh-56px-200px)]
  md:hidden
  relative
">
  <RoomViewport />
  <ViewportControlsFab className="absolute bottom-4 right-4" />
</div>
<BottomSheet>
  <FurniturePanel />
</BottomSheet>

タブレット (md: 768px ~ 1023px)

┌─────────────────┬──────────────────────┐ │ ヘッダー (固定) │ │ 高さ: 64px ├─────────────────┴──────────────────────┤ │ │ │ 3Dビューポート (70%) │ 右サイドパネル (30%) │ ┌─────────────┤ │ │ 家具パネル │ │ │ (スクロール) │ │ └─────────────┤ └────────────────────────────────────────┘
// タブレット
<div className="
  hidden md:flex lg:hidden
  h-[calc(100dvh-64px)]
">
  <div className="w-[70%] relative">
    <RoomViewport />
  </div>
  <div className="w-[30%] overflow-y-auto border-l border-[#D4D0C8]">
    <FurniturePanel />
  </div>
</div>

デスクトップ (lg: 1024px+)

┌──────────────────────────────────────────────────────┐ │ ヘッダー (固定) │ 高さ: 72px ├────────┬─────────────────────────────────┬────────────┤ │ │ │ │ │ 左 │ 3Dビューポート (中央) │ 右 │ │ ツール │ │ 家具 │ │ バー │ │ パネル │ │ (56px) │ │ (320px) │ │ │ │ │ └────────┴─────────────────────────────────┴────────────┘
// デスクトップ
<div className="
  hidden lg:grid
  grid-cols-[56px_1fr_320px]
  h-[calc(100dvh-72px)]
">
  <LeftToolbar />
  <div className="relative">
    <RoomViewport />
  </div>
  <div className="overflow-y-auto border-l border-[#D4D0C8]">
    <FurniturePanel />
    <RoomSettings />
  </div>
</div>

4.2 3Dビューポート Canvas サイズ管理

import { useThree } from '@react-three/fiber'
import { useResizeObserver } from '@/hooks/useResizeObserver'

export function RoomViewportCanvas() {
  const containerRef = useRef<HTMLDivElement>(null)

  // コンテナサイズに追従(100% × 100%)
  return (
    <div ref={containerRef} className="w-full h-full">
      <Canvas
        style={{ width: '100%', height: '100%' }}
        camera={{ position: [0, 5, 10], fov: 60 }}
        // デバイスピクセル比に対応(Retina)
        dpr={[1, 2]}
        gl={{
          antialias: true,
          powerPreference: 'high-performance',
          // モバイルではパフォーマンス優先
        }}
      >
        ...
      </Canvas>
    </div>
  )
}

4.3 3D UIオーバーレイのレスポンシブ

// モバイルではコントロールを最小化
<div className="
  absolute
  bottom-4 right-4        // モバイル: 右下
  md:top-4 md:right-4     // タブレット: 右上
  lg:bottom-6 lg:right-6  // デスクトップ: 右下(少し余白)
  flex flex-col gap-2
  bg-[rgba(26,29,26,0.7)] backdrop-blur-sm
  rounded-xl p-2
">
  <ViewportButton icon={<ZoomIn />} label="拡大" />
  <ViewportButton icon={<ZoomOut />} label="縮小" />
  <ViewportButton icon={<RotateCcw />} label="リセット" />
  {/* グリッドはデスクトップのみ表示 */}
  <div className="hidden lg:block">
    <ViewportButton icon={<Grid />} label="グリッド" toggle />
  </div>
</div>

5. 一般レイアウトパターン

5.1 コンテナ幅

// ページコンテナ
<div className="
  w-full max-w-screen-xl
  mx-auto
  px-4        // base: 16px
  sm:px-6     // sm: 24px
  lg:px-8     // lg: 32px
">

5.2 家具グリッド

// 商品一覧グリッド
<div className="
  grid
  grid-cols-2          // base: 2列
  sm:grid-cols-2       // sm: 2列
  md:grid-cols-3       // md: 3列
  lg:grid-cols-4       // lg: 4列
  xl:grid-cols-5       // xl: 5列
  gap-3                // base: 12px
  md:gap-4             // md: 16px
  lg:gap-6             // lg: 24px
">
  {products.map((p) => <FurnitureCard key={p.id} product={p} />)}
</div>

5.3 ヘッダー高さ

ブレークポイント高さ
base (mobile)56px
md (tablet)64px
lg (desktop)72px
<header className="
  fixed top-0 left-0 right-0 z-50 safe-top
  h-14       // 56px
  md:h-16    // 64px
  lg:h-18    // 72px (= h-[72px])
  bg-white border-b border-[#D4D0C8]
">

5.4 フォントサイズのレスポンシブ

// Playfair Display H1
<h1 className="
  text-2xl      // base: 24px
  md:text-3xl   // md: 30px
  lg:text-4xl   // lg: 36px
  xl:text-[2.5rem]  // xl: 40px (design-system.yml 定義値)
  font-playfair font-bold
">

// 商品名 H3 (Montserrat)
<h3 className="
  text-base     // base: 16px
  md:text-lg    // md: 18px
  lg:text-xl    // lg: 20px
  font-montserrat font-semibold
">

6. メーカー管理画面のレスポンシブ

6.1 アクセス制限ポリシー

デバイス機能
モバイル (base ~ md)閲覧のみ: 売上サマリー・通知確認
タブレット (md ~ lg)主要操作: 商品管理・注文確認
デスクトップ (lg+)フル機能: 統計・設定・一括操作
// 管理画面 モバイル制限バナー
export function MobileRestrictionBanner() {
  return (
    <div className="lg:hidden sticky top-0 z-40 bg-[#D4A843] text-white px-4 py-2 text-sm font-noto-sans-jp">
      <p>デスクトップでフル機能をご利用いただけます</p>
    </div>
  )
}

6.2 管理画面サイドナビゲーション

// デスクトップ: 固定サイドバー / モバイル: BottomTab または DrawerMenu
<nav className="
  // モバイル: 非表示
  hidden
  // デスクトップ: 固定サイドバー
  lg:flex lg:flex-col lg:fixed lg:left-0 lg:top-0 lg:bottom-0
  lg:w-64
  lg:bg-[#FAFAF7] lg:border-r lg:border-[#D4D0C8]
">

6.3 データテーブル

// モバイルではカード表示にフォールバック
<div className="hidden md:block">
  <DataTable data={products} columns={desktopColumns} />
</div>
<div className="md:hidden">
  <ProductCardList data={products} />
</div>

7. パフォーマンス考慮

7.1 画像

import Image from 'next/image'

// 商品画像: レスポンシブsizes設定
<Image
  src={product.image}
  alt={product.name}
  fill
  sizes="
    (max-width: 640px) 50vw,
    (max-width: 1024px) 33vw,
    20vw
  "
  className="object-cover"
/>

7.2 3Dモデル品質の段階的切り替え

// デバイス性能に応じてLOD (Level of Detail) を変更
const isMobile = useMediaQuery('(max-width: 768px)')

<FurnitureModel
  src={isMobile ? model.lowPolyUrl : model.highPolyUrl}
  // モバイル: 低ポリゴン、デスクトップ: 高ポリゴン
/>

7.3 h-dvh の使用

// 100vh ではなく 100dvh を使用(iOS Safari のダイナミックビューポート対応)
<div className="h-dvh">
  <RoomViewport />
</div>

8. アクセシビリティ × レスポンシブ

項目実装
フォーカスインジケーターfocus-visible:ring-2 focus-visible:ring-[#2C3E2D] 全サイズ共通
スキップリンクモバイル・デスクトップ共通で <a href="#main-content">
3Dビューポートモバイルでもキーボード操作可 (矢印キー: 回転, +/-: ズーム)
タッチターゲット全ブレークポイントで 44px 以上維持

9. チェックリスト

Phase 4 実装前確認:

  • tailwind.config.ts に全ブレークポイント設定済み
  • safe-area ユーティリティクラス追加済み
  • h-dvhh-screen の代わりに使用
  • 全インタラクティブ要素が min-h-[44px] を持つ
  • 3Dビューポートが3レイアウトパターン(mobile/tablet/desktop)で実装
  • BottomSheet に safe-bottom 適用済み
  • 管理画面のモバイル制限バナー実装済み
  • 画像に適切な sizes 属性設定済み
  • h-dvh / min-h-dvh を使用

Generated for RoomCraft - Phase 2: Design CCAGI SDK v3.14.4