モバイルファースト
モバイルファーストとは
モバイルファーストとは、モバイル端末向けのデザインを基準として最初に設計し、その後より大きな画面サイズ向けにデザインを拡張していく手法。
ブレイクポイント
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>
);
}