この課題のねらい
この演習は「Next.js らしいレイアウト」の感覚をつかむことが目的です。
特に大事なのは、ページごとに毎回ヘッダーを書くのではなく、
共通ヘッダーを layout.tsx にまとめる
どのページを開いても同じヘッダーが表示される
必要ならフッターも同じように共通化する
という「レイアウトを一段上で管理する」という発想です。
ここがつかめると、一気に「アプリ全体をデザインする視点」に近づきます。
共通ヘッダー作成(layout.tsx の基本)
layout.tsx が担当する役割
Next.js(App Router)では、app/layout.tsx が「全ページ共通の枠」を担当します。
ブラウザでどの URL を開いても、
html や body の基本タグ
共通のヘッダー
共通の余白やフォント設定
などは、この layout.tsx に書かれた内容になります。
各ページ側(app/page.tsx や app/about/page.tsx)は、「中身だけ」を書くイメージです。
シンプルな layout.tsx の例
まずは、共通ヘッダーだけを持つ、最小限の layout.tsx を作ってみましょう。
// app/layout.tsx
import type { ReactNode } from "react";
import Link from "next/link";
import "./globals.css";
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="ja">
<body style={{ margin: 0, fontFamily: "sans-serif" }}>
<header
style={{
padding: "12px 24px",
borderBottom: "1px solid #e5e7eb",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
backgroundColor: "white",
position: "sticky",
top: 0,
zIndex: 10,
}}
>
<div style={{ fontWeight: "bold" }}>Next.js × React 入門</div>
<nav style={{ display: "flex", gap: "16px", fontSize: "14px" }}>
<Link href="/">ホーム</Link>
<Link href="/about">このサイトについて</Link>
</nav>
</header>
<main style={{ padding: "24px" }}>{children}</main>
</body>
</html>
);
}
TSXここでやっていることを整理します。
RootLayout コンポーネントは、すべてのページを包む「一番外側のコンポーネント」です。
header タグの中に、共通のタイトルとナビゲーションを定義しています。
main の中の {children} に、各ページの中身が挿し込まれます。
つまり、どのページを表示しても、
上にヘッダー(タイトル+リンク)
下にそのページ固有の内容
という構成になります。
layout.tsx を使ったページ側のシンプル化
ページファイルでは「中身だけ」に集中する
ヘッダーを layout.tsx に移したことで、ページ側のコードはとてもシンプルになります。
例えばトップページをこう書けます。
// app/page.tsx
export default function HomePage() {
return (
<>
<h1>ホームページ</h1>
<p>ここはトップページです。</p>
</>
);
}
TSXここでは main やヘッダーは一切書いていません。
なぜなら、それらはすでに layout.tsx に書いてあるからです。
layout.tsx の <main>{children}</main> の children の部分に、
この HomePage の JSX がそのまま入っていくイメージです。
同様に、app/about/page.tsx もこう書けます。
// app/about/page.tsx
export default function AboutPage() {
return (
<>
<h1>このサイトについて</h1>
<p>Next.js × React 入門講座のサンプルサイトです。</p>
</>
);
}
TSXレイアウトのことは気にせず、「このページの中身は何か?」だけに集中できるのが、layout.tsx を使う一番のメリットです。
フッター追加(挑戦課題)
ヘッダーと同じノリでフッターを追加する
次は、ヘッダーと同じようにフッターも共通化してみましょう。
やることはシンプルで、layout.tsx に footer を追加するだけです。
例として、先ほどの RootLayout を少しだけ拡張します。
// app/layout.tsx
import type { ReactNode } from "react";
import Link from "next/link";
import "./globals.css";
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="ja">
<body
style={{
margin: 0,
fontFamily: "sans-serif",
minHeight: "100vh",
display: "flex",
flexDirection: "column",
}}
>
<header
style={{
padding: "12px 24px",
borderBottom: "1px solid #e5e7eb",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
backgroundColor: "white",
}}
>
<div style={{ fontWeight: "bold" }}>Next.js × React 入門</div>
<nav style={{ display: "flex", gap: "16px", fontSize: "14px" }}>
<Link href="/">ホーム</Link>
<Link href="/about">このサイトについて</Link>
</nav>
</header>
<main style={{ padding: "24px", flex: 1 }}>{children}</main>
<footer
style={{
padding: "12px 24px",
borderTop: "1px solid #e5e7eb",
fontSize: "12px",
color: "#6b7280",
backgroundColor: "white",
}}
>
© {new Date().getFullYear()} Next.js × React 入門講座
</footer>
</body>
</html>
);
}
TSXここで大事なポイントは次の通りです。
body に minHeight: "100vh" と display: "flex", flexDirection: "column" を指定しているので、画面全体が縦方向のフレックスレイアウトになります。
main に flex: 1 を付けているので、「中身部分」が空きスペースを埋め、フッターは常に一番下に張り付きやすくなります。
footer の中にコピーライトなどを入れておけば、どのページでも同じフッターが出ます。
これで、ヘッダーもフッターも「アプリ全体で共通」の状態になります。
レイアウト設計で意識してほしいこと
Next.js の layout.tsx を使うときに、意識してほしいのは次のようなことです。
ヘッダー・フッター・共通の余白やフォント設定は layout.tsx に集める。
各ページは「そのページ固有のコンテンツ」だけに集中する。
ナビゲーションやコピーライトを変更したくなったら layout.tsx を変えるだけで全ページに反映される。
これができると、
ページが増えてもレイアウトをまとめて管理できる
どのページも同じ「顔つき」になり、サービスとして統一感が出る
後からデザインを変えたくなっても修正箇所が最小限で済む
という状態になります。
もし余力があれば、次のような工夫も試してみると良いです。
ヘッダーにサイトロゴ風のテキストやアイコンを追加する
フッターに簡単なリンク(プライバシーポリシー等のダミー)を置いてみる
main の幅を maxWidth で制限して、中央寄せレイアウトにしてみる
そうすると、「Next.js アプリ」というより「ちゃんとした Web サービスの画面」にグッと近づいていきます。
