デザイン・カスタマイズ
UI に画像を使う場合のベストプラクティス
画像の種類と保存場所
CastMatrix で扱う画像は大きく2種類あります。
| 種類 | 例 | 保存場所 | 表示方法 |
|---|---|---|---|
| UI 画像(サイトデザインの一部) | ヒーロー画像・背景・ロゴ・デコ素材 | frontend/public/ に直接置く |
<img src="/ファイル名"> |
| キャスト画像(運用データ) | プロフィール写真・動画 | R2(管理画面からアップロード) | API 経由で自動表示 |
UI 画像の配置方法
frontend/public/ に置いたファイルはビルド後にルート直下に公開されます。
frontend/
└── public/
├── hero.jpg → https://あなたのドメイン/hero.jpg
├── bg-top.webp → https://あなたのドメイン/bg-top.webp
└── icons/
└── logo.svg → https://あなたのドメイン/icons/logo.svg
.astro ファイルから参照する場合:
<img src="/hero.jpg" alt="トップページのメイン画像" />
ファイル形式の選び方
| 用途 | 推奨形式 | 理由 |
|---|---|---|
| 写真・グラデーション | WebP | JPEG より 30〜50% 軽い。Safari/Chrome 対応済み |
| 写真(WebP 非対応環境も考慮) | JPEG + WebP 両方 | <picture> 要素でフォールバック |
| ロゴ・アイコン・線画 | SVG | 拡大縮小しても劣化しない |
| 透過が必要なデコ素材 | WebP または PNG | PNG は容量が大きいので WebP 優先 |
| アニメーション | WebP アニメ または 動画(<video>) |
GIF は非常に重いので避ける |
<img> タグのベストプラクティス
必ず指定するもの
<img
src="/hero.jpg"
alt="店舗のイメージ画像" <!-- 必須: スクリーンリーダー・SEO のため -->
width="800" <!-- 必須: レイアウトシフト防止 -->
height="600" <!-- 必須: レイアウトシフト防止 -->
loading="lazy" <!-- 推奨: ファーストビュー外は lazy -->
/>
ファーストビューの画像は loading="eager"
ページを開いてすぐ見える画像(ヒーロー・ロゴなど)は lazy だと逆効果です。
<!-- ヒーロー画像 → eager -->
<img src="/hero.jpg" alt="..." loading="eager" />
<!-- スクロール後に出てくる画像 → lazy(省略時のデフォルト) -->
<img src="/cast-sample.jpg" alt="..." loading="lazy" />
アスペクト比コンテナで縦横比を固定する
画像の縦横比を固定しないと、画像が読み込まれるたびにページが揺れます(レイアウトシフト)。
<!-- NG: 縦横比が固定されていない -->
<img src="/hero.jpg" class="w-full" />
<!-- OK: aspect-video (16:9) で固定 -->
<div class="w-full aspect-video overflow-hidden">
<img src="/hero.jpg" class="w-full h-full object-cover" />
</div>
<!-- OK: aspect-[3/4] (縦長・キャストカードと同じ比率) -->
<div class="w-full aspect-[3/4] overflow-hidden rounded-lg">
<img src="/sample.jpg" class="w-full h-full object-cover" />
</div>
object-fit の使い分け
<!-- object-cover: はみ出してもいいので比率を維持して全体を埋める(キャスト写真に最適) -->
<img class="w-full h-full object-cover object-center" />
<!-- object-contain: 余白が出てもいいので全体を収める(ロゴ・バナーに) -->
<img class="w-full h-full object-contain" />
<!-- object-top: 顔を上に寄せたい場合(縦長写真で顔を切らない) -->
<img class="w-full h-full object-cover object-top" />
背景画像のパターン
CSS inline style で指定する
<!-- セクション背景に画像を使う -->
<section
class="relative py-12 px-4 text-white text-center"
style="background-image: url('/bg-section.webp'); background-size: cover; background-position: center;"
<div class="absolute inset-0 bg-black/50"></div>
<div class="relative z-10">
<h2 class="text-2xl font-bold">見出しテキスト</h2>
</div>
</section>
<style> ブロックで CSS クラスを定義する(同じファイル内)
<style>
.hero-section {
background-image: url('/hero.webp');
background-size: cover;
background-position: center top;
background-attachment: fixed; /* パララックス効果 */
}
</style>
<div class="hero-section relative h-[60vw] max-h-[500px]">
<div class="absolute inset-0 bg-gradient-to-b from-black/20 to-black/60"></div>
<div class="relative z-10 flex items-center justify-center h-full text-white">
<h1 class="text-3xl font-bold">ようこそ</h1>
</div>
</div>
/* スマホでは fixed を無効化 */
@media (max-width: 767px) {
.hero-section {
background-attachment: scroll;
}
}
バナー画像の実装パターン
管理画面で登録したバナーは banners API から取得しています(home.astro 参照)。
バナーを画像として表示したい場合は home.astro のバナー表示部分を変更します。
<!-- home.astro — バナーを画像で表示する例 -->
{banners.length > 0 && (
<div class="px-4 py-3 space-y-2">
{banners.map((b: any) => (
b.link_url ? (
<a href={b.link_url} class="block rounded-lg overflow-hidden">
<img
src={b.image_url}
alt={b.title ?? 'バナー'}
class="w-full h-auto"
loading="lazy"
/>
</a>
) : (
<div class="rounded-lg overflow-hidden">
<img src={b.image_url} alt={b.title ?? 'バナー'} class="w-full h-auto" loading="lazy" />
</div>
)
))}
</div>
)}
よくあるミスと対策
ミス 1: 画像が重くてページが遅い
目安: トップページの合計画像サイズ → 1MB 以下に抑える
対策:
- WebP 形式を使う(JPEG の約半分のサイズ)
- ヒーロー画像は最大 1920px 幅で書き出す(それ以上は不要)
- Squoosh で無料圧縮できます
ミス 2: スマホで画像が変な比率で表示される
<!-- NG: 高さを固定しているが width と合っていない -->
<img src="/hero.jpg" class="w-full h-48" />
<!-- OK: aspect-ratio コンテナで比率を固定してから object-cover -->
<div class="w-full aspect-[16/5] overflow-hidden">
<img src="/hero.jpg" class="w-full h-full object-cover" />
</div>
ミス 3: alt テキストを省略する
SEO とアクセシビリティの両面で不利になります。
デコレーション目的(意味のない)画像は alt="" を明示してください。
<!-- 意味のある画像 -->
<img src="/exterior.jpg" alt="店舗の外観写真" />
<!-- 純粋な装飾(テキストで代替できる)→ alt="" を明示 -->
<img src="/divider.webp" alt="" role="presentation" />
ミス 4: public/ 以外のパスを指定してしまう
<!-- NG: src/ 内の画像は Astro のビルド処理が必要 -->
<img src="../assets/hero.jpg" />
<!-- OK: public/ に置いてルートパスで参照 -->
<img src="/hero.jpg" />
<picture> 要素で WebP + JPEG フォールバック
ブラウザが WebP に非対応の場合(古い端末)に JPEG を使いたいとき。
<picture>
<source srcset="/hero.webp" type="image/webp" />
<img src="/hero.jpg" alt="トップページのイメージ" class="w-full h-full object-cover" loading="eager" />
</picture>
各パーツの推奨画像サイズ
実装されているレイアウトから導出した推奨サイズです。
キャストプロフィール写真
| パーツ | アスペクト比 | 推奨最小サイズ | 推奨最大サイズ |
|---|---|---|---|
| キャストカード(一覧・ランキング) | 3:4(縦長) | 300 × 400 px | 600 × 800 px |
| キャスト詳細スライダー | 3:4(縦長) | 600 × 800 px | 1200 × 1600 px |
| スケジュール・ランキングのアイコン | 1:1(正方形) | 80 × 80 px | 200 × 200 px |
バナー・クーポン画像
バナー・クーポンページ(/coupon)およびトップページ(/home)に表示されます。
画像は横幅 100% で表示され、高さはアスペクト比に応じて自動調整されます。
| 種別 | 推奨アスペクト比 | 推奨サイズ | 備考 |
|---|---|---|---|
| バナー(告知・キャンペーン) | 3:1 〜 4:1(横長) | 1200 × 400 px | 横長が標準的で見映えがよい |
| クーポン | 2:1 〜 3:1(横長) | 1200 × 500 px | テキストが読める大きさで制作する |
| トップページ表示(home 上部) | 3:1 推奨 | 1200 × 400 px | 最大 3 件表示 |
注意点:
- 画像に文字を入れる場合は左右に余白を設けてください(スマートフォンでは幅が縮小されます)
- クーポンは有効期限・割引率など重要情報を画像内に入れることが多いため、文字サイズは大きめに
ロゴ画像(SiteHeader)
| 制約 | 値 |
|---|---|
| 表示高さ | 最大 40 px(h-10) |
| 表示幅 | 最大 160 px(max-w-[160px]) |
| 推奨比率 | 横長(例: 4:1 〜 6:1) |
| 推奨ファイル形式 | SVG(拡縮で劣化しない)または WebP |
| 背景 | 透過(白背景のヘッダーに対して)推奨 |
トップ動画のサムネイル/ヒーロー画像
| パーツ | アスペクト比 | 推奨サイズ |
|---|---|---|
トップ動画(top_video_url) |
16:9 | 1920 × 1080 px(フルHD) |
ヒーロー静止画(design-overview.md パターン A) |
任意 | 1440 × 600 px(横長が扱いやすい) |
まとめ早見表
| 用途 | 比率 | 最低 px |
|---|---|---|
| キャスト写真 | 3:4 | 300 × 400 |
| バナー | 3:1〜4:1 | 1200 × 300 |
| クーポン | 2:1〜3:1 | 1200 × 400 |
| ロゴ | 4:1〜6:1 | 240 × 40 |
| トップ動画 | 16:9 | 1280 × 720 |