1. ホーム
  2. Next.js

【Next.js】layout.tsx で共通レイアウトを作る方法|ページ間でヘッダー・フッターを共有する

Share

Web サイトを作ると、ヘッダーやフッター、ナビゲーションメニューのように「どのページでも同じように表示したい部分」が必ず出てきます。これをページごとに書いていては、修正のたびにすべてのファイルを直すことになり大変です。Next.js の App Router では、こうした共通部分を layout.tsx にまとめておくことで、全ページで自動的に共有できます。この記事では、必須となるルートレイアウトと children の役割、フォルダごとにレイアウトを入れ子にする方法、ページを移動しても状態が保たれる特徴、そして page.tsx との違いまでを、初心者向けに解説します。

layout.tsx とは何か

layout.tsx は、App Router で「複数のページに共通する枠組み」を定義するための特別なファイルです。app フォルダの中に置くと、その配下のすべてのページを包む形で使われます。page.tsx が「そのページ固有の中身」を担当するのに対し、layout.tsx は「その中身を囲む共通の外側」を担当します。両者の役割を整理しておきましょう。

ファイル役割
layout.tsxヘッダー・フッターなど、複数ページで共通の外枠
page.tsxそのURLでだけ表示される、ページ固有の中身

ルートレイアウトは必須

App Router では、app/layout.tsx(ルートレイアウト)が必ず1つ必要です。これはアプリ全体を包む一番外側のレイアウトで、<html> タグと <body> タグを含める決まりになっています。ここに書いた内容は、すべてのページで共有されます。

app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ja">
      <body>
        <header>サイト共通ヘッダー</header>
        {/* ここに各ページの中身が入る */}
        <main>{children}</main>
        <footer>© 2026 My Site</footer>
      </body>
    </html>
  );
}

ポイントは children(子要素)という props です。{children} と書いた場所に、表示中のページの中身(page.tsx の内容)が差し込まれます。上の例なら、ヘッダーとフッターはどのページでも共通で表示され、その間の <main> の部分だけがページごとに入れ替わります。ヘッダーやフッターを直したいときは、この app/layout.tsx を1か所直すだけで全ページに反映されます。

children で各ページが差し込まれる仕組み

children の型に使っている React.ReactNode は、「React が表示できるもの全般」を表す型です。文字列や数値、JSX の要素など、画面に描けるものはすべてこれに当てはまります。レイアウトは中身が具体的に何であるかを知る必要がなく、「渡されたものをここに表示する」とだけ決めておけばよいので、この型を使います。

たとえば app/page.tsx(トップページ)と app/about/page.tsx(Aboutページ)があるとき、/ を開けばトップの中身が、/about を開けば About の中身が、それぞれ layout.tsx{children} の位置に入ります。ヘッダーとフッターは共通のまま、中身だけが切り替わるわけです。

app/about/page.tsx
// このページの中身が layout.tsx の {children} に入る
export default function AboutPage() {
  return <h1>このサイトについて</h1>;
}

フォルダごとにレイアウトを入れ子にする

layout.tsx はルートだけでなく、任意のフォルダに置けます。あるフォルダに layout.tsx を置くと、その配下のページだけに追加の共通レイアウトが適用され、ルートレイアウトの中に入れ子(ネスト)になります。たとえば管理画面(dashboard)にだけサイドバーを付けたい、といった場合に便利です。

app/dashboard/layout.tsx
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div style={{ display: 'flex' }}>
      <aside>管理メニュー</aside>
      {/* dashboard 配下のページだけがここに入る */}
      <section>{children}</section>
    </div>
  );
}

この app/dashboard/layout.tsx は、/dashboard 以下のページにだけサイドバーを追加します。表示の構造としては、外側からルートレイアウト(ヘッダー・フッター)、その内側に dashboard のレイアウト(サイドバー)、さらにその内側に各ページの中身、という三重の入れ子になります。共通部分をどの範囲で共有したいかに応じて、レイアウトを置くフォルダを選べるのが App Router の大きな利点です。

ページを移動しても状態が保たれる

layout.tsx のもう一つの重要な特徴が、ページを移動してもレイアウトは再描画されず、状態が保たれるという点です。たとえばサイドバーのメニューを開いた状態でページを移動しても、そのサイドバーは作り直されないため、開いた状態のまま維持されます。共通のナビゲーションが遷移のたびにチラついたりリセットされたりしないので、快適な操作感につながります。

変わるのは {children} の部分、つまり移動先のページの中身だけです。この「変わらない外枠」と「切り替わる中身」という分担こそが、レイアウトを共通化する最大のメリットといえます。

うまく表示されないとき

ルートレイアウトに html・body がない

ルートレイアウト(app/layout.tsx)には <html><body> を必ず含める必要があります。これらを書き忘れるとエラーになります。ページ全体の土台となるタグなので、ルートレイアウトだけの決まりごととして覚えておきましょう。一方、フォルダ配下のネストしたレイアウトには <html><body> を書きません。

children を表示するのを忘れている

レイアウトの中に {children} を書き忘れると、ヘッダーやフッターは表示されるのに肝心のページの中身が出てこない、という状態になります。共通部分を書いたら、必ず {children} を置く場所を用意しているか確認しましょう。ページの中身がどこに入るかを決めるのは、この {children} です。

まとめ

Next.js App Router の layout.tsx は、ヘッダーやフッターのような共通部分を1か所にまとめ、全ページで共有するための仕組みです。app/layout.tsx のルートレイアウトは必須で、<html><body> を含み、{children} の位置に各ページの中身が差し込まれます。フォルダごとに layout.tsx を置けば、特定の範囲だけに追加のレイアウトを入れ子で適用でき、ページ移動時もレイアウトは再描画されず状態が保たれます。「変わらない外枠」と「切り替わる中身」を分けて考えることで、修正しやすく操作感のよいサイトが作れます。

参考ページ