こんにちは、かつコーチです。
前回はpage.tsxを使ったファイルベースルーティングの基本を解説し、フォルダを増やすだけでページが増えることを確認しました。
ページが増えてくると、今度は「どのページにも共通するヘッダーやフッターを、毎回コピペするのは面倒だ」という悩みが出てきます。
今回は、その悩みを解決してくれるlayout.tsxの使い方を詳しく見ていきましょう。
layout.tsxとは?
複数ページで共有される「土台」を定義するファイル
layout.tsxとは、同じフォルダ配下にある複数のページで共通して使われる、レイアウト(見た目の土台)を定義するファイルです。
create-next-app直後から存在するapp/layout.tsxは、ルートレイアウトと呼ばれ、サイト全体のすべてのページに適用される、最も外側のレイアウトです。
// app/layout.tsx
import type { Metadata } from "next";
import "./globals.css";
export const metadata: Metadata = {
title: "かつコーチのNext.js入門",
description: "初心者向けにNext.jsをやさしく解説します",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
<body>{children}</body>
</html>
);
}
なぜレイアウトを共通化する必要があるのか
前回作った/aboutや/blog/newsのようなページに、それぞれ個別で<html>タグやヘッダーを書いていくのは非効率です。
さらに、サイト共通のヘッダーの文言を1箇所直すだけで、全ページに変更を反映したい、という場面もよくあります。
layout.tsxを使えば、こうした「共通部分」と「ページごとに変わる部分」を分離して管理できます。
Reactシリーズで、共通のヘッダー・フッターを<Layout>というコンポーネントで囲んで使い回すテクニックを紹介しましたが、Next.jsではその考え方がフレームワークの標準機能として組み込まれている、とイメージするとわかりやすいです。
基本の書き方・実装手順
手順1:childrenの役割を理解する
layout.tsxのポイントは、childrenというPropsです。
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
<body>{children}</body>
</html>
);
}
このchildrenの部分に、同じフォルダ配下にあるpage.tsxの中身が、自動的に差し込まれます。
つまり、/aboutにアクセスすると、RootLayoutのchildren部分にapp/about/page.tsxの中身がはめ込まれた状態で表示される、という仕組みです。
手順2:ヘッダー・フッターを共通レイアウトに追加する
実際に、サイト全体で使うヘッダーとフッターをlayout.tsxに追加してみましょう。
// app/layout.tsx
import type { Metadata } from "next";
import "./globals.css";
export const metadata: Metadata = {
title: "かつコーチのNext.js入門",
description: "初心者向けにNext.jsをやさしく解説します",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
<body>
<header>
<p>かつコーチ | Next.js入門シリーズ</p>
</header>
{children}
<footer>
<p>© 2026 かつコーチ</p>
</footer>
</body>
</html>
);
}
この状態で/や/aboutなど、どのページにアクセスしても、共通のヘッダーとフッターが表示されるようになります。
手順3:特定のフォルダだけに適用されるレイアウトを作る
layout.tsxはapp直下だけでなく、任意のフォルダにも配置できます。
app/
├── layout.tsx ← 全ページ共通
├── page.tsx
└── blog/
├── layout.tsx ← blog配下のページだけに適用
└── news/
└── page.tsx
// app/blog/layout.tsx
export default function BlogLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div>
<nav>
<p>ブログ内メニュー</p>
</nav>
{children}
</div>
);
}
このように、フォルダごとにlayout.tsxを重ねて配置すると、ルートレイアウトの中に、さらにblog専用のレイアウトが入れ子になって適用されます。
「サイト全体で共通の部分」と「特定のセクションだけで共通の部分」を、フォルダの階層で自然に分けられるのが、この仕組みの強みです。
つまずきやすいポイント:私の実体験
childrenを書き忘れて画面が真っ白になった話
ここで、私が実際につまずいた経験を1つ共有します。
blog配下専用のヘッダーを追加しようとしてlayout.tsxを作ったとき、{children}を書き忘れたまま保存してしまい、/blog/newsにアクセスしても画面が真っ白になる、という状態にハマったことがあります。
❌ Before:childrenを書き忘れる
// app/blog/layout.tsx(バグあり)
export default function BlogLayout() {
return (
<div>
<nav>
<p>ブログ内メニュー</p>
</nav>
</div>
);
}
このコードでは、childrenというPropsを受け取っておらず、当然JSXの中でも表示していません。
その結果、page.tsx側の中身がどこにも差し込まれず、ナビゲーションだけが表示されて肝心のページ内容が消えてしまっていました。
✅ After:childrenを正しく受け取り、表示する
// app/blog/layout.tsx(修正後)
export default function BlogLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div>
<nav>
<p>ブログ内メニュー</p>
</nav>
{children}
</div>
);
}
このときは、コンソールにエラーが出るわけでもなく、TypeScriptの型チェックも通ってしまっていたため、原因を見つけるのに少し時間がかかりました。
layout.tsxを作るときは、「childrenを受け取る」「JSXの中で必ず{children}を書く」の2点をセットで確認する、という習慣がついてからは、同じミスをしなくなりました。
まとめ
この記事のポイント
layout.tsxは、複数のページで共有されるレイアウト(土台)を定義するファイルapp直下のlayout.tsxはルートレイアウトと呼ばれ、サイト全体に適用されるchildrenというPropsに、そのフォルダ配下のpage.tsxの中身が自動的に差し込まれる- フォルダごとに
layout.tsxを重ねて配置でき、特定のセクションだけの共通レイアウトも作れる childrenを書き忘れると、ページの中身が表示されなくなるので注意する
次に読むべき記事
これで、Next.jsの入門・環境構築編の5本が完了しました。
次回からは一歩進んで、URLの一部を可変にする動的ルートや、フォルダをURLに影響させずにグループ化するルートグループなど、より実践的なルーティングの書き方を解説していきます。
→ 次の記事:ルートグループ・動的ルートの書き方