dev TailwindCSS

TailwindCSS grid-template-areas|任意値で書くテクニック3選

TailwindCSS grid-template-areas は専用ユーティリティがなく任意値構文で書きます。col-span+row-span 方式との違い、領域名ミスマッチ、レスポンシブ切替の正解パターンを実例付きで解説します。

TailwindCSS grid-template-areas を使ったレイアウト、書けていますか?「公式ドキュメントに専用ユーティリティが見つからない」「複雑なグリッドは col-spanrow-span で頑張るしかない」「任意値構文って何のこと?」——これらは多くの開発者が途中で気付かず通り過ぎてしまう落とし穴です。

この記事では、grid-template-areas を Tailwind の任意値構文で書く3つのテクニックを、NG/OK のコードと実際の表示画像を並べながら解説します。

TailwindCSS で col-span と row-span を組み合わせて複雑なグリッドレイアウトを書いている例

「複雑なグリッドレイアウトは col-spanrow-span で頑張るもの」——そう思って書いていませんか?実はこれが今回の1つ目のテクニックの題材です。

私の体験談

その前に、私の体験談を紹介させてください。

私はこの記事を執筆するまで、TailwindCSS で grid-template-areas を任意値構文で書けることを知りませんでした。

正直に告白すると、Tailwind の公式ドキュメントの「Flexbox & Grid」セクションを見渡しても grid-template-areas / grid-area の専用ページはなく、「Tailwind では grid-template-areas は使えないんだな」と思っていました。複雑な2Dレイアウトを組みたいときは col-span / row-span の組み合わせで頑張るのが Tailwind の流儀だと思っていたんです。

今回この記事を書くために調べて、「えっ、[grid-template-areas:'...'] で書けるの?知らなかった」と素直に驚きました。さらに公式 GitHub Discussion を見ると、専用ユーティリティの追加を求める声は2020年から上がり続けていて、5年以上議論されている長寿テーマだと知りました。

公式ドキュメントの Flexbox & Grid セクションには grid-template-areas / grid-area の専用ページが存在しないため、最初にメニューを見渡して「無い」と判断すると、任意値構文で書ける可能性に気付かないまま col-span 方式に固定化してしまいやすい構成です。気付かず col-span+row-span で頑張っている方は、私以外にもいるんじゃないか——そう思ったのが、この記事を執筆するきっかけになりました。

同じように「Tailwind では grid-template-areas は使えないんだろうな」と思い込んでいる方の役に立てれば嬉しいです。

今回紹介する3つのテクニック

grid-template-areas まわりで開発者が躓きやすいポイントを、3つに絞って取り上げます。それぞれ「読者がやりがちな誤解 → NGコード → OKコード → 解説 → ポイント」の流れで進めます。コードはすべて Tailwind Play で再現できる形で示します。

テクニック1: 任意値構文を使わず col-span+row-span で頑張る

誤解シナリオ:

読者Aさんは、「ヘッダー / サイドバー / メイン / フッター」の複雑なレイアウトを Tailwind で作りたいと思っています。

  1. 公式ドキュメント(Grid Column Start / End - Tailwind CSS)で col-span-* を見つける
  2. 「これだ!」と思い col-span-* + row-span-* の組み合わせで子要素ごとに配置を指定
  3. 動作はするが、子要素のクラスを1つずつ追わないとレイアウト全体像が見えない…
  4. TailwindCSS で grid-template-areas が任意値構文で書けることを知らないまま、col-span 方式で固定化する

NGパターン:

<div class="bg-slate-700 p-8">
  <div class="grid grid-cols-3 grid-rows-3 gap-2 h-96">
    <div class="bg-white col-span-3 p-2">Header</div>
    <div class="bg-white row-span-2 p-2">Sidebar</div>
    <div class="bg-white col-span-2 row-span-2 p-2">Main</div>
    <div class="bg-white col-span-3 p-2">Footer</div>
  </div>
</div>
TailwindCSS で col-span と row-span を組み合わせて複雑なグリッドレイアウトを書いている例

動作はしていますが、レイアウトの意図が「子要素のクラスの寄せ集め」に分散し、要素が増えるほど全体像が掴みにくくなります。

OKパターン:

<div class="bg-slate-700 p-8">
  <div class="grid grid-cols-3 grid-rows-3 gap-2 h-96
              [grid-template-areas:'header_header_header'_'sidebar_main_main'_'footer_footer_footer']">
    <div class="bg-white [grid-area:header] p-2">Header</div>
    <div class="bg-white [grid-area:sidebar] p-2">Sidebar</div>
    <div class="bg-white [grid-area:main] p-2">Main</div>
    <div class="bg-white [grid-area:footer] p-2">Footer</div>
  </div>
</div>
TailwindCSS で grid-template-areas を任意値構文で書いた同じレイアウト

見た目は NG と全く同じですが、親の [grid-template-areas:...] 一箇所でレイアウトの全体像が把握できるようになりました。子要素は [grid-area:領域名] で「自分がどこに入るか」を宣言するだけです。

解説:

TailwindCSS には grid-template-areas 専用のユーティリティクラスが存在しないため、任意値(arbitrary values)構文 [プロパティ名:値] で書く必要があります。

任意値構文の固有のクセは3つあります。

  • スペースは _(アンダースコア)で表現する: 公式の Adding Custom Styles に明記された仕様。'header header header' ではなく 'header_header_header' と書く
  • 引用符のネスト: 外側 [ ]、内側 ' ' で記述する
  • 行の区切りも _ で表現: 行と行のあいだに _ を1つ挟み、複数の引用符で囲んだ文字列を連結する

なぜ専用ユーティリティが用意されないのか:

「だったら専用ユーティリティを用意してくれればいいのに」という声は、5年以上前から公式 GitHub で上がり続けていますGrid Template Area support? · Discussion #2634 は2020年10月起票、現在も議論継続)。

しかし Tailwind コミュニティ内では、grid-template-areas の値はプロジェクトごとに完全に固有で、flex-row のような汎用パターン化が困難なため、事実上「任意値で書く」が現状の解となっています。専用クラスが欲しい場合はコミュニティプラグイン(tailwindcss-grid-areas)もありますが、本記事では公式機能だけで完結させます。

ポイント:

複数行のレイアウトを領域名で組みたいときは、[grid-template-areas:'...'] + [grid-area:...] を任意値構文で書きましょう。アンダースコアでスペースを表現する点に注意してください。

テクニック2: 親と子で領域名がズレてサイレントに失敗する

誤解シナリオ:

読者Bさんはテクニック1を学んで [grid-template-areas:...] を書けるようになりました。

  1. 既存レイアウトで「サイドバー」を「ナビゲーション」に名前を変えて拡張したくなった
  2. 子要素を [grid-area:nav] に変更
  3. 親の [grid-template-areas:...] の方は sidebar のままで、nav への変更を忘れている
  4. 動かしてみると、エラーも警告も出ないのに「Nav と書いた要素が、なぜか予期しない場所にぽつんと置かれている」
  5. 「あれ?領域名はあってるはず…なんで配置が崩れる?」と困惑する

NGパターン:

<div class="bg-slate-700 p-8">
  <div class="grid grid-cols-3 grid-rows-3 gap-2 h-96
              [grid-template-areas:'header_header_header'_'sidebar_main_main'_'footer_footer_footer']">
    <div class="bg-white [grid-area:header] p-2">Header</div>
    <div class="bg-white [grid-area:nav] p-2">Nav</div>
    <div class="bg-white [grid-area:main] p-2">Main</div>
    <div class="bg-white [grid-area:footer] p-2">Footer</div>
  </div>
</div>
TailwindCSS で親に nav 領域がないため Nav 要素が予期しない位置に配置されている例

親の領域定義に nav は存在しません。Nav 要素はエラーを出さず、暗黙のグリッドセル(implicit grid)に自動配置されるため、画面の予期しない位置に飛ばされます。

OKパターン:

<div class="bg-slate-700 p-8">
  <div class="grid grid-cols-3 grid-rows-3 gap-2 h-96
              [grid-template-areas:'header_header_header'_'nav_main_main'_'footer_footer_footer']">
    <div class="bg-white [grid-area:header] p-2">Header</div>
    <div class="bg-white [grid-area:nav] p-2">Nav</div>
    <div class="bg-white [grid-area:main] p-2">Main</div>
    <div class="bg-white [grid-area:footer] p-2">Footer</div>
  </div>
</div>
TailwindCSS で親と子の領域名を nav で完全一致させ Nav が左列に正しく配置された例

親の [grid-template-areas:...]nav を含めて、子の [grid-area:nav] と完全一致させました。これで意図通り左列に Nav が配置されます。

解説:

子要素の grid-area が親の grid-template-areas に存在しない名前を指したとき、CSS Grid は黙って暗黙のグリッド(implicit grid)に自動配置します。これは CSS Grid の仕様上の挙動で、Tailwind 固有の問題ではありません。

ブラウザは無言なので、console.log も警告も期待できません。唯一の気付きポイントは「画面上で要素が変な位置にある」という外観になります。

任意値構文ではアンダースコアと領域名が混ざって視認しにくいため、領域名のタイポは特に発生しやすい状況です。親の [grid-template-areas:...] を変えたら、子の [grid-area:xxx] も同時に検索して整合させる のが事故防止の運用Tipsです。

ポイント:

領域名で配置するときは、親の [grid-template-areas:...] で定義した名前と、子の [grid-area:xxx] の名前を完全一致させましょう。タイポしてもエラーは出ず、暗黙のグリッドにサイレントに飛ばされ、画面上の位置のおかしさだけが手がかりになります。

テクニック3: モバイル用とデスクトップ用に HTML を二重に書く

誤解シナリオ:

読者Cさんはテクニック1を学び、grid-template-areas でレイアウトを組めるようになりました。

  1. モバイルでは縦積みに、デスクトップではサイドバー付き2D配置にしたい
  2. 「親の [grid-template-areas:...] 自体をブレークポイントで切り替えられる」と知らない
  3. やむを得ず、モバイル用とデスクトップ用の2セットの HTML を並べて、hidden md:grid / grid md:hidden で表示切替する
  4. 「Header の文言を変えるたびに2箇所更新…これメンテキツイ」と消耗する

NGパターン:

<div class="bg-slate-700 p-8">
  <!-- モバイル用 -->
  <div class="grid md:hidden grid-cols-1 grid-rows-4 gap-2 h-96
              [grid-template-areas:'header'_'sidebar'_'main'_'footer']">
    <div class="bg-white [grid-area:header] p-2">Header</div>
    <div class="bg-white [grid-area:sidebar] p-2">Sidebar</div>
    <div class="bg-white [grid-area:main] p-2">Main</div>
    <div class="bg-white [grid-area:footer] p-2">Footer</div>
  </div>
  <!-- デスクトップ用 -->
  <div class="hidden md:grid grid-cols-3 grid-rows-3 gap-2 h-96
              [grid-template-areas:'header_header_header'_'sidebar_main_main'_'footer_footer_footer']">
    <div class="bg-white [grid-area:header] p-2">Header</div>
    <div class="bg-white [grid-area:sidebar] p-2">Sidebar</div>
    <div class="bg-white [grid-area:main] p-2">Main</div>
    <div class="bg-white [grid-area:footer] p-2">Footer</div>
  </div>
</div>

→ 同じ子要素を2セット書いている。Header の文言を変えたら2箇所更新が必要。要素が増えるほどメンテコストが指数関数的に上がります。

OKパターン:

[grid-template-areas:'header'_'sidebar'_'main'_'footer']

md:grid-cols-3 md:grid-rows-3 md:[grid-template-areas:'header_header_header'_'sidebar_main_main'_'footer_footer_footer']"> <div class="bg-white [grid-area:header] p-2">Header</div> <div class="bg-white [grid-area:sidebar] p-2">Sidebar</div> <div class="bg-white [grid-area:main] p-2">Main</div> <div class="bg-white [grid-area:footer] p-2">Footer</div> </div> </div> -->

<div class="bg-slate-700 p-8">
  <div class="grid gap-2 h-96
              grid-cols-1 grid-rows-4

[grid-template-areas:'header'_'sidebar'_'main'_'footer']

md:grid-cols-3 md:grid-rows-3 md:[grid-template-areas:'header_header_header'_'sidebar_main_main'_'footer_footer_footer']"> <div class="bg-white [grid-area:header] p-2">Header</div> <div class="bg-white [grid-area:sidebar] p-2">Sidebar</div> <div class="bg-white [grid-area:main] p-2">Main</div> <div class="bg-white [grid-area:footer] p-2">Footer</div> </div> </div>

子要素は1セットだけ。親の [grid-template-areas:...]md: プレフィックスで切り替えるだけで、レスポンシブ対応完了です。

TailwindCSS で同じ HTML がモバイル幅では Header / Sidebar / Main / Footer の縦4段積みで表示されている例

モバイル幅では Header / Sidebar / Main / Footer が縦に4段積みで表示されます。

TailwindCSS で同じ HTML がデスクトップ幅では Header / Sidebar+Main / Footer の2D配置に切り替わる例

デスクトップ幅(md: 以上)では、同じ HTML から Header(上3列)/ Sidebar+Main / Footer(下3列)の2D配置に切り替わります。

解説:

Tailwind の任意値構文もブレークポイントプレフィックス(md:lg: など)と組み合わせ可能です。これは公式の任意値ドキュメントにも明記されている挙動です。

「これは基本的にインラインスタイルと同じですが、hoverlg などの修飾子が使える利点があります」
Adding Custom Styles - Arbitrary values

つまり md:[grid-template-areas:'...'] という書き方が CSS の @media (min-width: 768px) { grid-template-areas: '...' } に変換されます。インラインスタイルでは絶対できないことで、ここが Tailwind の任意値構文の真価です。

ただし注意点として、grid-template-columnsgrid-template-rows も同時に切り替える必要があります。親のセル数(行・列の数)が変わるなら、grid-cols-*grid-rows-*md: プレフィックスで切り替えましょう。

ポイント:

レイアウトをレスポンシブで切り替えたいときは、親の [grid-template-areas:'...'] 自体を md: プレフィックスで切り替えましょう。HTML の二重化は不要です。

まとめ

TailwindCSS grid-template-areas を任意値構文で書くときに躓きやすい3つのポイントを解説しました。

  • テクニック1: col-span+row-span で頑張らず、[grid-template-areas:'...'] + [grid-area:...] で書く。Tailwind には専用ユーティリティがないが、任意値構文で実現できる
  • テクニック2: 親と子で領域名を完全一致させる。タイポしてもエラーは出ず、画面上の位置のおかしさだけが手がかりになる
  • テクニック3: HTML を二重化せず、親の [grid-template-areas:...] 自体を md: で切り替える。1セットの HTML で2つのレイアウトを表現できる

任意値構文には「アンダースコアでスペースを表現」「引用符のネスト」など固有のクセがありますが、それを乗り越えればインラインスタイルでは到達できないレスポンシブ対応まで一気に実現できます。これまで col-span+row-span で頑張ってきた方は、ぜひ任意値構文への置き換えを試してみてください。

それではまた、別の記事でお会いしましょう。

最初の一歩を踏み出したい方へ

調べても調べても、何が正解かわからない——

WEB系へスキルチェンジするため、TailwindCSSを学び始めた頃の私です。

何から始めればいいのか、見当もつかない。記事を読んでも、情報がバラバラで混乱するばかり。

それでも諦めずに、調べて、手を動かして、試し続けました。

その結果、ようやく見えてきた「最初の一歩」を、この講座にまとめました。

同じ悩みを持つ方へ、最初の一歩を照らすガイドになれば嬉しいです。

👉 TailwindCSSハンズオン講座(無料の導入記事)

[PR]オススメ講座

「実際に作りながら学んでみたい!」という方には、講師「Shin Code」さんのUdemy講座がオススメ!

Shin Codeさんの講座「【Tailwindcss3.0】利用者急増中!作って学ぶ爆速で理解したい人向けのTailwindcss完全入門パック」では、個人用ポートフォリオサイトを作りながらTailwindCSSについて学習することができます。ポートフォリオサイトによくあるナビゲーションやヒーローセクションといった部品をTailwindCSSでどう書けばよいか、講師の方も一緒に手を動かしながら解説してくれています。

TailwindCSS初心者だった私でも一緒に手を動かして写経したら完成したので、個人的にオススメの講座です!

講座の詳細を見る

-dev, TailwindCSS