Astroこコンテンツスキーマをカスタマイズすることでフロントマターでアイキャッチ画像を追加することができます。ここでは、AstroのContent Collectionsと <Image>
コンポーネントを使って、記事にアイキャッチ画像を追加・表示する手順を紹介します。
前提:
- Content Collections APIを使ってブログ記事 (
blog
コレクション) を管理している -
src/content/config.ts
でスキーマを定義している
アイキャッチ画像 (featureImage) の追加手順
1.画像の準備と配置
まず、記事に使用したい画像ファイルを用意します。
用意した画像をプロジェクト内の src/assets/
ディレクトリ以下(例: src/assets/images/
)に配置します。ここに置くことで、Astroが画像を最適化してくれます。
your-project/
└── src/
├── assets/
│ └── images/ <-- ここに画像を配置 (例: post1.jpg, post2.png)
├── content/
│ └── blog/
├── pages/
└── layouts/
2.スキーマ定義の更新 (src/content/config.ts
)
src/content/config.ts
ファイルを開き、blog
コレクションの schema
を編集して、アイキャッチ画像用のフィールドを追加します。Astroの image()
ヘルパー関数を使います。
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
const blogCollection = defineCollection({
type: 'content',
// スキーマ定義を ({ image }) => z.object({...}) の形に変更する必要があるかも
schema: ({ image }) => z.object({
title: z.string(),
pubDate: z.coerce.date(),
description: z.string().optional(),
tags: z.array(z.string()).optional(),
url: z.string().optional(),
// ↓ アイキャッチ画像用のフィールドを追加
featureImage: image().optional(), // 画像はオプショナルにする場合
featureImageAlt: z.string().optional(), // 代替テキストもオプショナルに
// ↑ ここまで追加
}),
});
export const collections = {
'blog': blogCollection,
};
-
schema:
の後の定義を({ image }) => z.object({...})
という形式に変更します。image
はimage()
ヘルパー関数を使うために必要です -
featureImage: image()
: 画像フィールドを定義します。.refine()
で画像の最小幅などを検証したり、.optional()
で画像がない記事も許容するように設定できます -
featureImageAlt: z.string()
: 画像の代替テキスト(alt属性)用のフィールドです。画像に合わせて.optional()
にしておくと良いでしょう
3.Markdown フロントマターの更新
アイキャッチ画像を設定したい記事のMarkdownファイル (src/content/blog/
内) を開き、フロントマターに featureImage
と featureImageAlt
を追記します。
---
title: '私の最初の投稿'
pubDate: 2025-04-14
tags: ["Astro", "Blog"]
# ↓ アイキャッチ画像の情報を追加
featureImage: '../../assets/images/post1.jpg' # Markdownファイルから画像ファイルへの相対パス
featureImageAlt: 'ノートパソコンとコーヒーカップが置かれた机'
# ↑ ここまで追加
---
記事の本文...
-
featureImage:
には、このMarkdownファイルから見た画像ファイルへの相対パス を指定します。例のようにsrc/assets/images/
に置いた場合は、../../assets/images/画像ファイル名
のようになります。 -
featureImageAlt:
には、画像の内容を具体的に説明する代替テキストを記述します。これはアクセシビリティのために非常に重要です。
4.テンプレートでの画像表示 (.astro
ファイル)
アイキャッチ画像を表示したいテンプレートファイル(例: 個別記事ページの src/pages/[...slug].astro
や、一覧ページの src/pages/blog/[...page].astro
)を開き、<Image>
コンポーネントを使って画像を表示します。
個別記事ページ (src/pages/[...slug].astro
) での表示例:
---
// src/pages/[...slug].astro
import { getCollection, getEntry } from 'astro:content';
import BaseLayout from '../layouts/BaseLayout.astro';
import { Image } from 'astro:assets'; // ← Imageコンポーネントをインポート
// --- getStaticPaths と props の受け取り (変更なし) ---
const { post } = Astro.props;
const { Content } = await post.render();
---
<BaseLayout title={post.data.title}>
<article>
<h1>{post.data.title}</h1>
{/* ↓ アイキャッチ画像を表示 */}
{post.data.featureImage && post.data.featureImageAlt && (
<Image
src={post.data.featureImage}
alt={post.data.featureImageAlt}
width={720} {/* 表示したい幅を指定 */}
aspectRatio="16:9" {/* アスペクト比を指定すると高さは自動計算されることが多い */}
format="webp" {/* 最適なフォーマットを指定 (任意) */}
quality={80} {/* 画質を指定 (任意) */}
loading="lazy" {/* 遅延読み込み (任意) */}
decoding="async" {/* 非同期デコード (任意) */}
/>
)}
{/* ↑ ここまで */}
<p>公開日: {post.data.pubDate.toLocaleDateString()}</p>
{/* ... 他のコンテンツ ... */}
<Content />
</article>
</BaseLayout>
-
import { Image } from 'astro:assets';
を忘れずに追加します。 -
post.data.featureImage
とpost.data.featureImageAlt
が両方存在する場合にのみ<Image>
を表示するように条件分岐 (&&
) します。 -
<Image>
コンポーネントを使用します。-
src={post.data.featureImage}
: スキーマで処理された画像データを渡します。 -
alt={post.data.featureImageAlt}
: 必須 です。代替テキストを渡します。 -
width
: 画像の表示幅を指定します。 -
aspectRatio
またはheight
: アスペクト比か高さを指定すると、レイアウトシフトを防げます。 -
format
,quality
,loading
,decoding
など、様々な最適化オプションを指定できます。
-
開発サーバーで確認
content/config.ts
を変更したので、一度開発サーバーを 再起動 するのが確実です (Ctrl+C
で停止し、再度 npm run dev
など)。
ブラウザでアイキャッチ画像を設定した記事ページや一覧ページにアクセスし、画像が正しく表示されているか確認してください。画像の読み込みやレイアウト崩れがないかもチェックしましょう。