Next.jsによるWebアプリケーション開発概論

CSSレイアウトの基本:FlexboxとGridで要素を配置する

2画面設計基礎:レイアウトを組み、スタイルで整える
Next.jsTailwind CSSアプリ開発開発Web開発

この節で学ぶこと

この節では、Next.js の中で Tailwind CSS を使いながら、要素を並べる基本 を覚えます。

中心になるのは FlexboxGrid です。Flexbox は 1 次元の並び、つまり「横に並べる」「縦に積む」「中央に寄せる」といった操作が得意で、Grid は 行と列をまとめて扱う 2 次元レイアウトが得意です。

Next.js は App Router でも通常の CSS と Tailwind CSS を使えます。Tailwind では flexgridgrid-cols-2gap-4md:flex-row のような utility class を JSX に直接書いてレイアウトを組み立てます。

この節のゴールは、次の感覚を持つことです。

「1列なら Flexbox、表のような面配置なら Grid」

そして、スマホでは縦、広い画面では横、というような切り替えを Tailwind のレスポンシブ接頭辞で書けるようになることです。Tailwind のレスポンシブ指定は sm:md:lg: などの形式で行います。

まず完成イメージを見る

最初に、今日の終わりに作れるようになる小さな画面を見ます。

次のコードを app/page.tsx に書くと、見出しとカード一覧を持つシンプルなレイアウトになります。

export default function Page() {
  return (
    <main className="min-h-screen bg-gray-50 p-6">
      <section className="mx-auto max-w-5xl">
        <h1 className="text-2xl font-bold">商品一覧</h1>
        <p className="mt-2 text-sm text-gray-600">
          Flexbox と Grid で配置を練習します。
        </p>

        <div className="mt-6 grid gap-4 md:grid-cols-3">
          <article className="rounded-xl border bg-white p-4">カード1</article>
          <article className="rounded-xl border bg-white p-4">カード2</article>
          <article className="rounded-xl border bg-white p-4">カード3</article>
        </div>
      </section>
    </main>
  )
}

このコードの中心は gridgap-4md:grid-cols-3 です。

今は意味を全部覚えなくて大丈夫です。今日は、この画面を「少しずつ分解して理解する」ことが目的です。Grid の列数は grid-cols-* で指定でき、要素間の間隔は gap-* で指定できます。

Flexbox と Grid の違いを最初に掴む

覚え方

Flexbox は、横一列か縦一列 を扱うときに強いです。

Grid は、行と列をまとめて設計したいとき に強いです。MDN でも、Flexbox は 1 次元レイアウト、Grid は 2 次元レイアウトとして整理されています。

頭の中では、こう分けると分かりやすいです。

  • ボタンを横に並べたい → Flexbox
  • カードを 2 列や 3 列で並べたい → Grid
  • ヘッダーの左右に要素を置きたい → Flexbox
  • ダッシュボードの面配置を作りたい → Grid

1枚の図で覚える

Rendering diagram…

この図の通りです。

迷ったらまず「1列の話か、面の話か」を考えると判断しやすいです。

練習1 Flexbox で縦に積む

まずは一番簡単なところから始めます。

次のコードをそのまま app/page.tsx に書いてください。

export default function Page() {
  return (
    <main className="p-6">
      <div className="flex flex-col gap-4">
        <div className="rounded-lg border p-4">お知らせ</div>
        <div className="rounded-lg border p-4">新着情報</div>
        <div className="rounded-lg border p-4">お問い合わせ</div>
      </div>
    </main>
  )
}

見るポイントは 3 つです。

  • flex で Flexbox を有効にしている
  • flex-col で縦方向にしている
  • gap-4 で要素同士の間隔を空けている Tailwind では display: flex に相当する flex クラスがあり、方向は flex-colflex-row で切り替えられます。間隔は gap-* で指定できます。

練習2 Flexbox で横に並べる

次に、縦並びを横並びへ変えます。

flex-colflex-row に変えてください。

export default function Page() {
  return (
    <main className="p-6">
      <div className="flex flex-row gap-4">
        <div className="rounded-lg border p-4">保存</div>
        <div className="rounded-lg border p-4">下書き</div>
        <div className="rounded-lg border p-4">削除</div>
      </div>
    </main>
  )
}

これで、3つの箱が横に並びます。

ここで覚えてほしいのは、「同じ flex でも、方向クラスを変えるだけで画面の印象が大きく変わる」ということです。Flexbox の基本はまずここです。

練習3 Flexbox で左右に散らす

次は、ヘッダーらしい配置を作ります。

タイトルを左、ボタンを右へ置きます。

export default function Page() {
  return (
    <main className="p-6">
      <header className="flex items-center justify-between rounded-xl border p-4">
        <h1 className="text-xl font-bold">ダッシュボード</h1>
        <button className="rounded-md border px-4 py-2">新規作成</button>
      </header>
    </main>
  )
}

ここでは新しく justify-between を使っています。

左右の端へ要素を押し広げるクラスです。ヘッダー、ナビゲーション、一覧上部のツールバーなどで非常によく使います。Flexbox は、こうした「1行の中の位置調整」が得意です。

練習4 Grid で 2 列に並べる

次は Grid に切り替えます。

次のコードを打ってください。

export default function Page() {
  return (
    <main className="p-6">
      <div className="grid grid-cols-2 gap-4">
        <article className="rounded-xl border p-4">カード1</article>
        <article className="rounded-xl border p-4">カード2</article>
        <article className="rounded-xl border p-4">カード3</article>
        <article className="rounded-xl border p-4">カード4</article>
      </div>
    </main>
  )
}

ここでは、

  • grid で Grid を有効化
  • grid-cols-2 で 2 列
  • gap-4 で間隔

という構成です。Tailwind では列数を grid-cols-* で指定できます。Grid は複数カードの一覧や、ダッシュボードの領域分けに向いています。

練習5 Grid を 3 列に増やす

今のコードの grid-cols-2grid-cols-3 に変えてみてください。

export default function Page() {
  return (
    <main className="p-6">
      <div className="grid grid-cols-3 gap-4">
        <article className="rounded-xl border p-4">カード1</article>
        <article className="rounded-xl border p-4">カード2</article>
        <article className="rounded-xl border p-4">カード3</article>
        <article className="rounded-xl border p-4">カード4</article>
        <article className="rounded-xl border p-4">カード5</article>
        <article className="rounded-xl border p-4">カード6</article>
      </div>
    </main>
  )
}

これで 3 列になります。

Grid のよいところは、列数を変えるだけで画面の骨組みがかなり簡単に調整できることです。

練習6 スマホでは縦、広い画面では 3 列

次はレスポンシブ対応です。

次のコードを打ってください。

export default function Page() {
  return (
    <main className="p-6">
      <div className="grid grid-cols-1 gap-4 md:grid-cols-3">
        <article className="rounded-xl border p-4">カード1</article>
        <article className="rounded-xl border p-4">カード2</article>
        <article className="rounded-xl border p-4">カード3</article>
      </div>
    </main>
  )
}

この意味はこうです。

  • 最初は grid-cols-1 だから 1 列
  • md: 以上では grid-cols-3 だから 3 列

Tailwind のレスポンシブ設計は mobile-first です。つまり、接頭辞なしが小さい画面向けの基本で、md: などで上書きしていきます。

練習7 Flexbox と Grid を組み合わせる

実際の画面では、Flexbox だけ、Grid だけで終わることは少ないです。

よくあるのは、「上部は Flexbox、一覧は Grid」という組み合わせです。次のコードを打ってください。

export default function Page() {
  return (
    <main className="min-h-screen bg-gray-50 p-6">
      <section className="mx-auto max-w-5xl">
        <header className="flex items-center justify-between">
          <div>
            <h1 className="text-2xl font-bold">商品一覧</h1>
            <p className="mt-2 text-sm text-gray-600">
              Flexbox と Grid を組み合わせます。
            </p>
          </div>
          <button className="rounded-lg border px-4 py-2">新規追加</button>
        </header>

        <div className="mt-6 grid grid-cols-1 gap-4 md:grid-cols-3">
          <article className="rounded-xl border bg-white p-4">バッグ</article>
          <article className="rounded-xl border bg-white p-4">財布</article>
          <article className="rounded-xl border bg-white p-4">キーケース</article>
        </div>
      </section>
    </main>
  )
}

このコードでは、

  • ヘッダー部分は Flexbox
  • カード一覧部分は Grid です。

これがかなり現実的な使い分けです。1行の並びは Flexbox、一覧や面配置は Grid。まずはこの感覚を覚えてください。

今ここで覚えるべき最低限のルール

Flexbox でよく使うクラス

次の 5 つは、まず覚える価値があります。

<div className="flex" />
<div className="flex-col" />
<div className="flex-row" />
<div className="items-center" />
<div className="justify-between" />

これだけで、縦並び、横並び、上下中央、左右分散の基本がかなり触れます。Tailwind は display や flex-direction を個別クラスで指定できます。

Grid でよく使うクラス

次の 4 つをまず使えるようにしておくと強いです。

<div className="grid" />
<div className="grid-cols-1" />
<div className="grid-cols-2" />
<div className="grid-cols-3" />

一覧画面、カード群、管理画面でかなり使います。列数変更の感覚が大事です。

間隔は gap-* で付ける

Flexbox でも Grid でも、間隔はまず gap-* を使うと整理しやすいです。

<div className="gap-2" />
<div className="gap-4" />
<div className="gap-6" />

古い書き方では個別に mr-*mb-* を多用することがありますが、並びの間隔は gap が素直です。Tailwind も gap utilities を明確に提供しています。

手を動かす確認問題

問題1

次のコードを、ボタンが横並びになるように直してください。

export default function Page() {
  return (
    <main className="p-6">
      <div>
        <button className="rounded border px-4 py-2">保存</button>
        <button className="rounded border px-4 py-2">下書き</button>
      </div>
    </main>
  )
}

答え

export default function Page() {
  return (
    <main className="p-6">
      <div className="flex gap-4">
        <button className="rounded border px-4 py-2">保存</button>
        <button className="rounded border px-4 py-2">下書き</button>
      </div>
    </main>
  )
}

解説

flex を付けると横方向の並びが有効になり、gap-4 でボタン間の間隔が空きます。Flexbox は 1 行の並びに向いています。

問題2

次のカード一覧を、広い画面では 2 列、狭い画面では 1 列にしてください。

export default function Page() {
  return (
    <main className="p-6">
      <div>
        <article className="rounded-xl border p-4">カード1</article>
        <article className="rounded-xl border p-4">カード2</article>
      </div>
    </main>
  )
}

答え

export default function Page() {
  return (
    <main className="p-6">
      <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
        <article className="rounded-xl border p-4">カード1</article>
        <article className="rounded-xl border p-4">カード2</article>
      </div>
    </main>
  )
}

解説

Grid を使い、grid-cols-1 を基本にして、md:grid-cols-2 で広い画面だけ 2 列へ変えています。Tailwind のレスポンシブ指定は mobile-first です。

まとめ

Next.js で Tailwind CSS を使って画面を作るとき、レイアウトの基本は Flexbox と Grid の使い分け です。

Flexbox は 1 次元の並び、Grid は 2 次元の面配置に向いています。

Tailwind では、これらを flexflex-colgridgrid-cols-*gap-* のようなクラスで直接 JSX に書いて組み立てます。

レスポンシブ対応は md: などの接頭辞で行います。

この節でいちばん大切なのは、全部を暗記することではありません。

打つと並びが変わる列数を変えると画面の骨組みが変わる、この感覚を持つことです。

ここまで触れたなら、次の節で Tailwind CSS の基本クラスを学ぶ準備は十分です。

教材トップへ戻る