コンテンツにスキップ

レイアウト

レイアウトは、ページテンプレートのような再利用可能なUI構造を作成するために使用されるAstroコンポーネントです。

ヘッダーやナビゲーションバー、フッターなど、ページ間で共有される共通のUIを提供するAstroコンポーネントには、慣習的に「レイアウト」という用語が使われます。典型的なAstroのレイアウトコンポーネントは、Astro、Markdown、またはMDXのページに以下を提供します。

  • ページシェル<html>, <head>, <body> タグ)
  • 個々のページコンテンツが挿入される場所を指定する<slot />

ただし、レイアウトコンポーネントに何か特別なところがあるわけではありません。他のAstroコンポーネントと同様に、propsを受け取り他のコンポーネントをインポートして使用できます。UIフレームワークコンポーネントクライアントサイドスクリプトも含められます。ページ全体のシェルを提供する必要すらなく、代わりに部分的なUIテンプレートとしても使用可能です。

レイアウトコンポーネントは一般的にプロジェクト内のsrc/layoutsディレクトリに配置されますが、これは必須ではなく、プロジェクト内のどこに置いても構いません。レイアウトコンポーネントをページと同じ場所に置くこともでき、その場合はレイアウト名の先頭に_を付けます

src/layouts/MySiteLayout.astro
---
import BaseHead from '../components/BaseHead.astro';
import Footer from '../components/Footer.astro';
const { title } = Astro.props
---
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<BaseHead title={title}/>
</head>
<body>
<nav>
<a href="#">ホーム</a>
<a href="#">ブログ</a>
<a href="#">お問い合わせ</a>
</nav>
<h1>{title}</h1>
<article>
<slot /> <!-- ここにコンテンツが挿入されます -->
</article>
<Footer />
</body>
</html>
src/pages/index.astro
---
import MySiteLayout from '../layouts/MySiteLayout.astro';
---
<MySiteLayout title="ホームページ">
<p>レイアウトに包まれたページのコンテンツ</p>
</MySiteLayout>

📚 スロットについてもっと学ぶ。

ページレイアウトは、ページフォーマットをもたないMarkdownページとMDXページに対して特に便利です。

Astroでは、layoutというフロントマターの特別なプロパティを使用して、ページのレイアウトとして使用する.astroコンポーネントを指定できます。

src/pages/page.md
---
layout: ../layouts/BaseLayout.astro
title: "Hello, World!"
author: "Matthew Phillips"
date: "2022年8月9日"
---
すべてのフロントマターのプロパティは、Astroのレイアウトコンポーネントのpropsとして利用できます。
`layout`プロパティは、Astroが提供する唯一の特別なプロパティです。
`src/pages/`内のMarkdownとMDXファイルの両方で使用できます。

MarkdownまたはMDXページの典型的なレイアウトは以下を含みます。

  1. MarkdownまたはMDXページのフロントマターとその他のデータにアクセスするためのfrontmatterプロパティ。
  2. ページのMarkdownやMDXコンテンツをレンダリングする場所を示すためのデフォルトの<slot />
src/layouts/BaseLayout.astro
---
// 1. frontmatter propによりフロントマターとその他のデータにアクセスできます
const { frontmatter } = Astro.props;
---
<html>
<head>
<!-- スタイルやmetaタグなど、その他のhead要素をここに追加します -->
<title>{frontmatter.title}</title>
</head>
<body>
<!-- 共通のヘッダーやフッターなど、他のUIコンポーネントをここに追加します -->
<h1>{frontmatter.title} {frontmatter.author}</h1>
<!-- 2. レンダリングされたHTMLはデフォルトスロットに渡されます -->
<slot />
<p>投稿日: {frontmatter.date}</p>
</body>
</html>

MarkdownLayoutPropsまたはMDXLayoutPropsを使用して、レイアウトのPropsを設定できます。

src/layouts/BaseLayout.astro
---
import type { MarkdownLayoutProps } from 'astro';
type Props = MarkdownLayoutProps<{
// フロントマターのpropsをここで定義します
title: string;
author: string;
date: string;
}>;
// `frontmatter`や`url`などのMarkdownのレイアウトプロパティに
// 型安全にアクセスできます
const { frontmatter, url } = Astro.props;
---
<html>
<head>
<link rel="canonical" href={new URL(url, Astro.site).pathname}>
<title>{frontmatter.title}</title>
</head>
<body>
<h1>{frontmatter.title} {frontmatter.author}</h1>
<slot />
<p>投稿日: {frontmatter.date}</p>
</body>
</html>

MarkdownとMDXレイアウトは、Astro.propsを介して次の情報にアクセスできます。

  • file - ファイルの絶対パス(たとえば/home/user/projects/.../file.md)。
  • url - ページであれば、そのページのURL(/en/guides/markdown-content)。
  • frontmatter - MarkdownまたはMDXドキュメントのすべてのフロントマター。
    • frontmatter.file - トップレベルのfileプロパティと同じ。
    • frontmatter.url - トップレベルのurlプロパティと同じ。
  • headings - MarkdownまたはMDXドキュメントの見出し(h1 -> h6)と、関連するメタデータのリスト。このリストは次の型に従います:{ depth: number; slug: string; text: string }[]
  • (Markdownのみ) rawContent() - 生のMarkdownドキュメントを文字列として返す関数。
  • (Markdownのみ) compiledContent() - HTML文字列にコンパイルしたMarkdownドキュメントを返す関数。

Markdownのブログ記事がレイアウトに渡すAstro.propsオブジェクトは以下のようになるでしょう。

Astro.props = {
file: "/home/user/projects/.../file.md",
url: "/en/guides/markdown-content/",
frontmatter: {
/** ブログ記事のフロントマター */
title: "Astro 0.18 Release",
date: "Tuesday, July 27 2021",
author: "Matthew Phillips",
description: "Astro 0.18 is our biggest release since Astro launch.",
/** 生成された値 */
file: "/home/user/projects/.../file.md",
url: "/en/guides/markdown-content/"
},
headings: [
{
"depth": 1,
"text": "Astro 0.18 Release",
"slug": "astro-018-release"
},
{
"depth": 2,
"text": "Responsive partial hydration",
"slug": "responsive-partial-hydration"
}
/* ... */
],
/** Markdownでのみ利用可能 */
rawContent: () => "# Astro 0.18 Release\nA little over a month ago, the first public beta [...]",
compiledContent: () => "<h1>Astro 0.18 Release</h1>\n<p>A little over a month ago, the first public beta [...]</p>",
}

MDXレイアウトに、フロントマターには存在しない(または存在しようがない)情報を渡す必要がある場合があります。この場合、代わりに<Layout />コンポーネントをインポートして使用し、他のコンポーネントと同様にpropsを渡せます。

src/pages/posts/first-post.mdx
---
layout: ../../layouts/BaseLayout.astro
title: '初めてのMDX記事'
publishDate: '2022年9月21日'
---
import BaseLayout from '../../layouts/BaseLayout.astro';
export function fancyJsHelper() {
return "YAMLでやってみよう!";
}
<BaseLayout title={frontmatter.title} fancyJsHelper={fancyJsHelper}>
MDXを使用した新しいAstroブログへようこそ!
</BaseLayout>

すると、レイアウトのAstro.propsを介して値が利用でき、MDXコンテンツは<slot />コンポーネントが書かれている場所に挿入されます。

src/layouts/BaseLayout.astro
---
const { title, fancyJsHelper } = Astro.props;
---
<!-- -->
<h1>{title}</h1>
<slot /> <!-- コンテンツはここに挿入されます -->
<p>{fancyJsHelper()}</p>
<!-- -->

📚 MarkdownとMDXのガイドでAstroのMarkdownとMDXサポートについてもっと学ぶ。

.md.mdx.astroに対し同一のレイアウトを使用する

セクションタイトル: .md、.mdx、.astroに対し同一のレイアウトを使用する

一つのAstroレイアウトで、.md.mdxファイルのfrontmatterオブジェクトと、.astroファイルから渡された名前付きのpropsを受け取るように書くことができます。

以下の例では、レイアウトは、フロントマターのYAMLのtitleプロパティまたはtitle属性を渡すAstroコンポーネントからページタイトルを受け取ってそれを表示します。

src/components/MyLayout.astro
---
const { title } = Astro.props.frontmatter || Astro.props;
---
<html>
<head></head>
<body>
<h1>{title}</h1>
<slot />
</body>
</html>

レイアウトコンポーネントは、ページ全体に相当するHTMLを含む必要はありません。レイアウトをより小さなコンポーネントに分割し、各コンポーネントを組み合わせてより柔軟なページレイアウトを作成できます。このパターンは、複数のレイアウト間でコードを共有したい場合に便利です。

たとえば、BlogPostLayout.astroレイアウトはブログ記事のタイトル、日付、作者にスタイルを付けるとします。そして、サイト全体で共通のBaseLayout.astroは、ナビゲーションやフッター、SEOメタタグ、グローバルスタイル、フォントなどのページテンプレートの残りを処理します。また、他の入れ子になったコンポーネントと同様に、ブログ記事から受け取ったpropsを他のレイアウトに渡すこともできます。

src/layouts/BlogPostLayout.astro
---
import BaseLayout from './BaseLayout.astro'
const {frontmatter} = Astro.props;
---
<BaseLayout url={frontmatter.url}>
<h1>{frontmatter.title}</h1>
<h2>投稿者: {frontmatter.author}</h2>
<slot />
</BaseLayout>