コンテンツにスキップ

レイアウト

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

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

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

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

レイアウトコンポーネントがページシェルを含んでいる場合、レイアウトコンポーネントの<html>タグは他の全てのタグの親である必要があります。

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

レイアウトのサンプル

---
// 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>
  <style>
    h1 {
      font-size: 2rem;
    }
  </style>
</html>
---
import MySiteLayout from '../layouts/MySiteLayout.astro';
---
<MySiteLayout title="ホームページ">
  <p>レイアウトに包まれたページのコンテンツ</p>
</MySiteLayout>
スロットについてもっと学ぶ。

レイアウトでTypeScriptを使用する

どのAstroレイアウトでも、propsに型を定義することで、型安全性と自動補完を導入できます:

---
interface Props { 
  title: string;
  description: string;
  publishDate: string;
  viewCount: number;
}
const { title, description, publishDate, viewCount } = Astro.props;
---
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="description" content={description}>
    <title>{title}</title>
  </head>
  <body>
    <header>
      <p>Published on {publishDate}</p>
      <p>Viewed by {viewCount} folks</p>
    </header>
    <main>
      <slot />
    </main>
  </body>
</html>

Markdownのレイアウト

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

Astroは、ファイルベースルーティングを使用してsrc/pages/内に配置される個別の.mdファイル (EN)向けに、特別なlayoutフロントマタープロパティを提供しています。これにより、ページレイアウトとして使用する.astroコンポーネントを指定できます。このコンポーネントを使用すると、メタタグ(例: <meta charset="utf-8">)やスタイルなどの<head>コンテンツをMarkdownページに提供できます。デフォルトでは、指定されたコンポーネントはMarkdownファイルからデータに自動的にアクセスできます。

ただしコンテンツコレクション (EN)を使ってコンテンツをクエリ・レンダリングする場合、このプロパティは特別なものとして認識されません。

---
layout: ../layouts/BlogPostLayout.astro
title: "Hello, World!"
author: "Matthew Phillips"
date: "2022年8月9日"
---
すべてのフロントマターのプロパティは、Astroのレイアウトコンポーネントのpropsとして利用できます。

`layout`プロパティは、Astroが提供する唯一の特別なプロパティです。

`src/pages/`内のMarkdownファイルで使用できます。

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

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

MarkdownLayoutPropsを使用して、レイアウトのProps型 (EN)を設定できます。

---
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>
    <meta charset="utf-8">
    <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レイアウトのProps

Markdownレイアウトは、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 }[]
  • rawContent() - 生のMarkdownドキュメントを文字列として返す関数。
  • compiledContent() - MarkdownドキュメントをHTML文字列にコンパイルして返すasync関数。

:::noteMarkdownレイアウトは、Astro.propsからMarkdownファイルの利用可能なプロパティ (EN)すべてにアクセスできますが、2つの重要な違いがあります:

  • 見出し情報(つまりh1 -> h6要素)は、getHeadings()関数ではなく、headings配列を介して利用できます。

  • fileurlは、ネストされたfrontmatterプロパティ(つまりfrontmatter.urlfrontmatter.file)としても利用できます。:::

レイアウトを手動でインポートする(MDX)

MDXファイルのフロントマターでも、特別なMarkdownのlayoutプロパティを使って、同じように指定したレイアウトコンポーネントへfrontmatterheadingsのpropsを直接渡すことができます。

MDXレイアウトに、フロントマターには存在しない(または存在しようがない)情報を渡すには、代わりに<Layout />コンポーネントをインポートして使用できます。これは他のAstroコンポーネントと同じように動作し、propsは自動で受け取りません。必要なpropsを直接渡してください。

---
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 />コンポーネントが書かれている場所に挿入されます。

---
const { title, fancyJsHelper } = Astro.props;
---
<html>
  <head>
    <!-- -->
    <meta charset="utf-8">
  </head>
  <body>
    <!-- -->
    <h1>{title}</h1>
    <slot /> <!-- your content is injected here -->
    <p>{fancyJsHelper()}</p>
    <!-- -->
  </body>
</html>

レイアウトを使用する場合(frontmatterのlayoutプロパティを使用するか、レイアウトをインポートするかに関わらず)、レイアウトに <meta charset="utf-8"> タグを含める必要があります。AstroはMDXページにこのタグを自動的に追加しなくなったためです。

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

レイアウトの入れ子

レイアウトコンポーネントは、ページ全体に相当する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>
貢献する コミュニティ スポンサー