monukedayo.
Astroで画像を扱う

2026/1/22

Astroで画像を扱う

Astroで画像を扱う方法

Astro プログラミング

Astroで画像を

Images
Learn how to use images in Astro.
docs.astro.build

Astroには<Image>というコンポーネントが存在します。
これはAstroの画像最適化機能を使う場合に使用しますが、これを積極的に利用していこうという回。

Imageコンポーネントの利用方法

index.astro
---
import { Image } from "astro:assets"
import gazou from "@/assets/gazou.png"
---
...
<Image src={gazou} alt="これは画像です。" />
...

みたいに使うことが出来ます。このサイトにはありませんが、ロゴなんかを表示するときに。
このサイトで使用されている箇所としては、

  • カバー画像
  • 記事内の画像

だけですね。ここしか無い。

デフォルト設定でwebpに変換されます。

カバー画像として扱う

このブログではフロントマターにcoverというプロパティが存在し、相対パスで指定することが出来ます。

src/content.config.ts
import { defineCollection } from "astro:content";
import { glob } from "astro/loaders";
import { z } from "astro/zod";
const blog = defineCollection({
loader: glob({ pattern: '**/*.{md,mdx}', base: './contents/blog' }),
schema: ({ image }) => z.object({
title: z.string(),
description: z.string().optional(),
pubDate: z.date(),
tags: z.array(z.string()).optional(),
draft: z.boolean().default(false),
categorie: z.string().optional(),
cover: image().optional()
})
})
export const collections = { blog };

上のようになっています。schemaのところに({ image })とありますが、コレが重要です。

後は使用箇所で使用していくだけです。

[id].astro
---
import Layout from "@/layouts/Layout.astro";
import Toc from "@/components/Toc.astro";
import { Image } from "astro:assets";
import defaultCover from '@/assets/default.jpg';
import { getCollection, render } from "astro:content";
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts.map(post => ({
params: { id: post.id },
props: { post }
}));
}
const { post } = Astro.props;
const { Content, headings } = await render(post);
---
<Layout>
<section class="pt-16 h-screen min-h-screen">
<div class="container mx-auto w-full max-w-7xl flex flex-col px-6">
<div class="flex flex-col items-center justify-center text-center py-6">
<Image class="rounded-lg aspect-21/9 object-cover object-center mb-4" src={post.data.cover || defaultCover} alt={post.data.title} />
<h1 class="text-3xl font-bold">{post.data.title}</h1>
<p class="text-gray-600 mt-2">{post.data.pubDate.toLocaleDateString('ja-jp')}</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-2 w-full py-8">
<div class="md:col-span-2 prose prose-base w-full">
<Content />
</div>
<div class="sticky top-24 hidden md:block">
<Toc headings={headings} />
</div>
</div>
</div>
</section>
</Layout>

これは当サイトで使用しているコードです。<Image>srcに渡しています。

OGP画像として

OGP画像として渡す場合には一工夫(?)いります。

まずastro.config.mjsでサイトのURLを設定する必要があります。

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
site: 'https://ast.monukedayo.cc',
});

siteのところですね。

あとはURLを組み立てるだけです。私はLayout.astroで組み立てています。

Layout.astro
---
import type { ImageMetadata } from 'astro';
import defaultCover from '@/assets/default.jpg';
interface meta {
title: string,
description?: string,
image?: ImageMetadata
}
interface Props {
meta?: meta
}
const ogImage = meta?.image ? new URL(meta.image.src, Astro.url).toString() : new URL(defaultCover.src, Astro.url).toString()
---
<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
{/* 他のプロパティ */}
<meta property="og:image" content={ogImage} />
</head>
<body>
<slot />
</body>
</html>

雑な気がしますが、動いてるのでヨシ!!

終わり

触りの部分だけですが、他の部分は詳しく書いている記事を参照していただくとして…(他力本願寺)

あまり深く考えなくてもパフォーマンスは高く保たれます。私はそういう考えで書いてます。

以上ッ!!!