モバイルファースト
モバイルファーストとは
モバイルファーストとは、モバイル端末向けのデザインを基準として最初に設計し、その後より大きな画面サイズ向けにデザインを拡張していく手法。
ブレイクポイント
Material-UIのブレイクポイント
xs: '0'      // スマートフォン(縦向き)
sm: '600px'  // スマートフォン(横向き)
md: '900px'  // タブレット
lg: '1200px' // ノートPC
xl: '1536px'  // デスクトップ
Tailwind CSSのブレイクポイント
// デフォルトのブレイクポイント
sm: '640px'   // スマートフォン(横向き)
md: '768px'   // タブレット
lg: '1024px'  // ノートPC
xl: '1280px'  // デスクトップ
2xl: '1536px' // 大画面デスクトップ
Material-UIでのレスポンシブ実装
useMediaQueryの使用
import { useTheme } from '@mui/material/styles';
import useMediaQuery from '@mui/material/useMediaQuery';
function ResponsiveComponent() {
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
  
  return (
    <div>
      {isMobile ? (
        <MobileView />
      ) : (
        <DesktopView />
      )}
    </div>
  );
}
Gridの使用
import { Grid, Card, CardContent } from '@mui/material';
function ResponsiveGrid() {
  return (
    <Grid container spacing={2}>
      <Grid item xs={12} md={6} lg={4}>
        <Card>
          <CardContent>
            <Typography variant="h5">タイトル</Typography>
            <Typography variant="body2">コンテンツ</Typography>
          </CardContent>
        </Card>
      </Grid>
      {/* 繰り返し */}
    </Grid>
  );
}
スタイリングでのブレイクポイント
import { styled } from '@mui/material/styles';
const ResponsiveBox = styled('div')(({ theme }) => ({
  padding: theme.spacing(2),
  [theme.breakpoints.up('md')]: {
    padding: theme.spacing(4),
  },
  [theme.breakpoints.up('lg')]: {
    padding: theme.spacing(6),
  },
}));
レスポンシブイメージ
import { styled } from '@mui/material/styles';
const ResponsiveImage = styled('img')(({ theme }) => ({
  width: '100%',
  height: 'auto',
  [theme.breakpoints.up('md')]: {
    height: '16rem',
  },
  [theme.breakpoints.up('lg')]: {
    height: '24rem',
  },
}));
Tailwind CSSでのレスポンシブ実装
基本的なレイアウト
// モバイルファーストのグリッドレイアウト
function ResponsiveGrid() {
  return (
    <div className="container mx-auto px-4">
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
        {/* カードコンポーネント */}
        <div className="bg-white rounded-lg shadow p-4">
          <h2 className="text-lg md:text-xl lg:text-2xl">タイトル</h2>
          <p className="text-sm md:text-base">コンテンツ</p>
        </div>
        {/* 繰り返し */}
      </div>
    </div>
  );
}
ナビゲーションバー
function ResponsiveNavbar() {
  return (
    <nav className="bg-gray-800">
      <div className="max-w-7xl mx-auto px-4">
        <div className="flex items-center justify-between h-16">
          {/* ロゴ */}
          <div className="flex-shrink-0">
            <img className="h-8 w-8" src="/logo.svg" alt="Logo" />
          </div>
          
          {/* デスクトップメニュー */}
          <div className="hidden md:block">
            <div className="ml-10 flex items-baseline space-x-4">
              <a href="#" className="text-white px-3 py-2 rounded-md">Home</a>
              <a href="#" className="text-gray-300 px-3 py-2 rounded-md">About</a>
              {/* 他のメニュー項目 */}
            </div>
          </div>
          
          {/* モバイルメニューボタン */}
          <div className="md:hidden">
            <button className="text-gray-400 hover:text-white">
              <span className="block h-6 w-6">☰</span>
            </button>
          </div>
        </div>
      </div>
    </nav>
  );
}
レスポンシブイメージ
function ResponsiveImage() {
  return (
    <img
      src="/image.jpg"
      alt="Responsive image"
      className="w-full h-auto object-cover md:h-64 lg:h-96"
    />
  );
}
コンテンツの優先順位付け
function PriorityContent() {
  return (
    <div className="flex flex-col md:flex-row">
      {/* 主要コンテンツ */}
      <main className="w-full md:w-2/3 order-2 md:order-1">
        <h1>メインコンテンツ</h1>
      </main>
      
      {/* サイドバー */}
      <aside className="w-full md:w-1/3 order-1 md:order-2">
        <nav>サイドメニュー</nav>
      </aside>
    </div>
  );
}