CastMatrix

デザイン・カスタマイズ

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 pxh-10
表示幅 最大 160 pxmax-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