目次
- はじめに
- 今日作るもの
- STEP 1:Day16用HTMLファイルを作る
- STEP 2:タイトルをDay16用に直す
- STEP 3:詳細ボタンにクリック処理を追加する
- STEP 4:x-dataでモーダルの開閉状態を用意する
- STEP 5:モーダル背景を追加する
- STEP 6:モーダル本体を追加する
- STEP 7:閉じるボタンでモーダルを閉じる
- STEP 8:モーダルの見た目を整える
- 完成コード
- 今回追加したもの
- 使ったTailwind CSSのclass
- 表示確認
- 補足:z-indexの優先順位について
- 今日分かったこと
- 次回やること
- シリーズ記事
はじめに
この記事は、Tailwind CSSで管理画面UIを1ステップずつ作る学習記録です。
過去記事は末尾の「シリーズ記事」にまとめています。
今日作るもの
Day16では、作品一覧の「詳細」ボタンをクリックすると表示される詳細モーダルを作ります。
Alpine.jsの x-data、@click、x-show を使い、ボタン操作でモーダルを開閉できるようにします。
モーダルは通常画面より前面に表示したいので、fixed、inset-0、z-50 を使って重なり順も確認します。
STEP 1:Day16用HTMLファイルを作る
Day16では、Day15で作った管理画面レイアウトを元にして、作品の詳細モーダルを追加します。
そのため、Day15の完成形をコピーして進めます。
cp day15-hamburger-menu.html day16-detail-modal.html
エクスプローラーでコピーしても大丈夫です。
現在の構成に、Day16用ファイルが追加される形です。
tailwind-learning/
├── day01-heading.html
├── day02-card-base.html
├── day03-image-card.html
├── day04-card-text.html
├── day05-card-buttons.html
├── day06-card-complete.html
├── day07-button-colors.html
├── day08-admin-header.html
├── day09-pc-sidebar.html
├── day10-pc-admin-layout.html
├── day11-item-table.html
├── day12-table-style.html
├── day13-responsive-layout.html
├── day14-alpine-basic.html
├── day15-hamburger-menu.html
├── day16-detail-modal.html
└── images/
└── sample-poster.png
STEP 2:タイトルをDay16用に直す
day16-detail-modal.html の <title> を、Day16用に変更します。
修正前
<title>Day 15 ハンバーガーメニューを作る</title>
修正後
<title>Day 16 詳細モーダルを作る</title>
このSTEPでは、ブラウザタブに表示されるタイトルだけ を変更します。
画面に表示されているヘッダー、ハンバーガーメニュー、サイドバー、テーブル、スマホ用カード部分はまだ触りません。
STEP 3:詳細ボタンにクリック処理を追加する
STEP2では、<title> をDay16用に変更しました。
次は、作品一覧の 詳細ボタン をクリックしたときに、モーダルを開く処理を追加します。
このSTEPでは、まずPC用テーブルの「詳細」ボタンにクリック処理を追加します。
スマホ用カードにも「詳細」ボタンがありますが、学習の流れを分かりやすくするため、本文ではPC用テーブルを中心に進めます。
完成コードでは、スマホ用カード側の「詳細」ボタンにも同じ処理を追加します。
修正前
<button class="px-2 py-1 text-xs border border-gray-300 text-gray-700 rounded hover:bg-gray-200">
詳細
</button>
修正後
<button
@click="modalOpen = true"
class="px-2 py-1 text-xs border border-gray-300 text-gray-700 rounded hover:bg-gray-200"
>
詳細
</button>
今回追加するもの
| 追加するもの | 内容 |
|---|---|
@click="modalOpen = true" |
詳細ボタンを押したときにモーダルを開く |
修正箇所
PC用テーブルには、作品データが3件あります。
そのため、PC用テーブル内の「詳細」ボタン 3か所 に、同じ @click="modalOpen = true" を追加します。
PC用テーブル 1件目の詳細ボタン
PC用テーブル 2件目の詳細ボタン
PC用テーブル 3件目の詳細ボタン
スマホ用カードにも詳細ボタンがありますが、このSTEPではPC用テーブルを中心に確認します。
完成コードでは、スマホ用カード側の詳細ボタンにも同じクリック処理を追加します。
補足:スマホ用カード側の詳細ボタンについて
本文では、PC用テーブルの詳細ボタンを中心に説明しています。
ただし、完成コードではスマホ用カードからも詳細モーダルを開けるようにするため、スマホ用カード側の「詳細」ボタンにも同じ処理を追加します。
@click="modalOpen = true"
今回のポイント
@click="modalOpen = true" を追加することで、詳細ボタンをクリックしたときに modalOpen の値を true にできます。
modalOpen: false → モーダルを閉じている状態
modalOpen: true → モーダルを開いている状態
ただし、今の時点ではまだ modalOpen を用意していません。
そのため、このSTEPだけではまだ正しく動きません。
次のSTEPで、x-data に modalOpen: false を追加して、モーダルの開閉状態を用意します。
STEP 4:x-dataでモーダルの開閉状態を用意する
STEP3では、詳細ボタンに @click="modalOpen = true" を追加しました。
次は、Alpine.jsで モーダルが開いているかどうか を管理する状態を用意します。
Day15ですでに、ハンバーガーメニュー用に body へ x-data="{ menuOpen: false }" を追加しています。
今回はそこに、詳細モーダル用の modalOpen: false を追加します。
修正前
<body
x-data="{ menuOpen: false }"
class="bg-gray-100"
>
修正後
<body
x-data="{ menuOpen: false, modalOpen: false }"
class="bg-gray-100"
>
今回追加するもの
| 追加するもの | 内容 |
|---|---|
modalOpen: false |
最初は詳細モーダルを閉じた状態にする |
今回のポイント
modalOpen は、詳細モーダルの表示状態を管理するための変数です。
@click="modalOpen = true"
と組み合わせることで、詳細ボタンを押したときに modalOpen を true にできます。
このSTEPでは、まだモーダル本体は表示されません。
次のSTEPで、x-show="modalOpen" を使ってモーダル背景を表示します。
STEP 5:モーダル背景を追加する
STEP4では、body の x-data に modalOpen: false を追加しました。
次は、modalOpen が true のときだけ表示される モーダル背景 を追加します。
このSTEPでは、まず画面全体を覆う半透明の背景だけを作ります。
モーダル本体は次のSTEPで追加します。
追加する場所
スマホ用メニューの下、main の前に追加します。
修正前
<!-- スマホ用メニュー -->
<div
x-show="menuOpen"
class="fixed top-0 right-0 z-40 w-64 h-screen bg-gray-700 text-white p-6 md:hidden shadow-lg"
>
...
</div>
<main class="flex flex-col md:flex-row items-start">
修正後
<!-- スマホ用メニュー -->
<div
x-show="menuOpen"
class="fixed top-0 right-0 z-40 w-64 h-screen bg-gray-700 text-white p-6 md:hidden shadow-lg"
>
...
</div>
<!-- モーダル背景 -->
<div
x-show="modalOpen"
class="fixed inset-0 z-50 bg-black/50"
>
</div>
<main class="flex flex-col md:flex-row items-start">
今回追加するもの
| 追加するもの | 内容 |
|---|---|
x-show="modalOpen" |
modalOpen が true のときだけモーダル背景を表示する |
今回追加するclass
| class | 内容 |
|---|---|
fixed |
画面上に固定表示する |
inset-0 |
上下左右すべてを 0 にして画面全体に広げる |
z-50 |
ハンバーガーメニューより前面に表示する |
bg-black/50 |
黒背景を50%の透明度で表示する |
今回のポイント
fixed inset-0 を使うことで、モーダル背景を画面全体に広げられます。
modalOpen: false → モーダル背景を非表示
modalOpen: true → モーダル背景を表示
Day15のハンバーガーメニューは z-40 にしました。
今回のモーダル背景は z-50 にすることで、ハンバーガーメニューより前面に表示されます。
このSTEPでは、まだ背景だけなので、詳細情報を表示する箱は出ません。
次のSTEPで、モーダル本体を追加します。
STEP 6:モーダル本体を追加する
STEP5では、modalOpen が true のときに表示されるモーダル背景を追加しました。
次は、そのモーダル背景の中に、作品の詳細情報を表示する白い箱を追加します。
この白い箱が、画面中央に表示される モーダル本体 です。
修正前
<!-- モーダル背景 -->
<div
x-show="modalOpen"
class="fixed inset-0 z-50 bg-black/50"
>
</div>
<main class="flex flex-col md:flex-row items-start">
修正後
<!-- 詳細モーダル -->
<div
x-show="modalOpen"
class="fixed inset-0 z-50 bg-black/50 flex items-center justify-center p-4"
>
<div class="bg-white rounded-lg shadow-lg w-full max-w-md p-6">
<h3 class="text-lg font-bold">
サンプル映画タイトル
</h3>
<div class="mt-4 space-y-2 text-sm text-gray-700">
<p>
平均評価:4.2
</p>
<p>
レビュー数:12件
</p>
<p>
ここに作品の詳細情報を表示します。
</p>
</div>
</div>
</div>
<main class="flex flex-col md:flex-row items-start">
今回変更するポイント
STEP5では、背景だけを表示していました。
<div
x-show="modalOpen"
class="fixed inset-0 z-50 bg-black/50"
>
</div>
今回は、その中に白いモーダル本体を入れます。
<div class="bg-white rounded-lg shadow-lg w-full max-w-md p-6">
<!-- モーダル本体 -->
</div>
今回追加するclass
| class | 内容 |
|---|---|
flex |
モーダル本体を配置しやすくする |
items-center |
モーダル本体を縦方向の中央に配置する |
justify-center |
モーダル本体を横方向の中央に配置する |
p-4 |
画面端とモーダルの間に余白を付ける |
bg-white |
モーダル本体の背景を白にする |
max-w-md |
モーダル本体の最大幅を決める |
shadow-lg |
モーダル本体に影を付ける |
space-y-2 |
詳細情報の行間を空ける |
今回のポイント
fixed inset-0 で画面全体に広げた背景に、flex items-center justify-center を追加すると、モーダル本体を画面中央に配置できます。
背景:fixed inset-0 z-50 bg-black/50
本体:bg-white rounded-lg shadow-lg
このSTEPでは、まだ閉じるボタンはありません。
次のSTEPで、モーダル内に閉じるボタンを追加します。
STEP 7:閉じるボタンでモーダルを閉じる
STEP6では、モーダル背景とモーダル本体を追加しました。
次は、モーダル内に 閉じるボタン を追加します。
modalOpen を false にすることで、モーダルを閉じられるようにします。
修正前
<div class="bg-white rounded-lg shadow-lg w-full max-w-md p-6">
<h3 class="text-lg font-bold">
サンプル映画タイトル
</h3>
<div class="mt-4 space-y-2 text-sm text-gray-700">
<p>
平均評価:4.2
</p>
<p>
レビュー数:12件
</p>
<p>
ここに作品の詳細情報を表示します。
</p>
</div>
</div>
修正後
<div class="bg-white rounded-lg shadow-lg w-full max-w-md p-6">
<div class="flex justify-between items-center">
<h3 class="text-lg font-bold">
サンプル映画タイトル
</h3>
<button
@click="modalOpen = false"
class="text-2xl text-gray-500 hover:text-gray-800"
>
×
</button>
</div>
<div class="mt-4 space-y-2 text-sm text-gray-700">
<p>
平均評価:4.2
</p>
<p>
レビュー数:12件
</p>
<p>
ここに作品の詳細情報を表示します。
</p>
</div>
</div>
今回追加するもの
| 追加するもの | 内容 |
|---|---|
@click="modalOpen = false" |
閉じるボタンを押したときにモーダルを閉じる |
今回追加するclass
| class | 内容 |
|---|---|
justify-between |
タイトルと閉じるボタンを左右に配置する |
items-center |
タイトルと閉じるボタンを縦方向の中央に揃える |
text-2xl |
閉じるボタンの文字サイズを大きくする |
text-gray-500 |
閉じるボタンの文字色をグレーにする |
hover:text-gray-800 |
hover時に閉じるボタンの文字色を濃くする |
今回のポイント
@click="modalOpen = false" を付けることで、閉じるボタンを押したときにモーダルを非表示にできます。
modalOpen: true
↓
閉じるボタンを押す
↓
modalOpen: false
↓
モーダルが閉じる
このSTEPで、詳細ボタンを押してモーダルを開き、× ボタンで閉じる流れができました。
次のSTEPでは、モーダルの見た目をもう少し整えます。
STEP 8:モーダルの見た目を整える
STEP7までで、詳細ボタンを押すとモーダルが表示され、閉じるボタンで閉じられるようになりました。
最後に、モーダルの見た目を少し整えます。
今回は、モーダル本体に枠線や余白、下部の閉じるボタンを追加して、管理画面の詳細表示らしくします。
修正前
<div class="bg-white rounded-lg shadow-lg w-full max-w-md p-6">
<div class="flex justify-between items-center">
<h3 class="text-lg font-bold">
サンプル映画タイトル
</h3>
<button
@click="modalOpen = false"
class="text-2xl text-gray-500 hover:text-gray-800"
>
×
</button>
</div>
<div class="mt-4 space-y-2 text-sm text-gray-700">
<p>
平均評価:4.2
</p>
<p>
レビュー数:12件
</p>
<p>
ここに作品の詳細情報を表示します。
</p>
</div>
</div>
修正後
<div class="bg-white rounded-lg shadow-lg w-full max-w-md p-6 border">
<div class="flex justify-between items-center">
<h3 class="text-lg font-bold">
サンプル映画タイトル
</h3>
<button
@click="modalOpen = false"
class="text-2xl text-gray-500 hover:text-gray-800"
>
×
</button>
</div>
<div class="mt-4 space-y-2 text-sm text-gray-700">
<p>
平均評価:4.2
</p>
<p>
レビュー数:12件
</p>
<p>
ここに作品の詳細情報を表示します。
</p>
</div>
<div class="mt-6 text-right">
<button
@click="modalOpen = false"
class="px-3 py-1.5 text-sm border border-gray-300 text-gray-700 rounded hover:bg-gray-200"
>
閉じる
</button>
</div>
</div>
今回追加するclass
| class | 内容 |
|---|---|
border |
モーダル本体に枠線を付ける |
mt-6 |
閉じるボタンの上に余白を付ける |
text-right |
閉じるボタンを右寄せにする |
px-3 |
ボタンの左右に余白を付ける |
py-1.5 |
ボタンの上下に余白を付ける |
border-gray-300 |
ボタンの枠線を薄いグレーにする |
hover:bg-gray-200 |
hover時に薄いグレー背景にする |
今回のポイント
モーダル右上の × ボタンだけでも閉じられますが、下部にも「閉じる」ボタンを置くと、操作が分かりやすくなります。
右上の ×:すぐ閉じる操作
下部の閉じる:内容を確認したあと閉じる操作
これで、Day16の詳細モーダルは完成です。
完成コード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Day 16 詳細モーダルを作る</title>
<script src="https://cdn.tailwindcss.com"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head>
<body
x-data="{ menuOpen: false, modalOpen: false }"
class="bg-gray-100"
>
<header class="bg-gray-900 text-white px-6 py-4 flex justify-between items-center">
<h1 class="text-xl">
Admin Dashboard
</h1>
<div class="flex items-center gap-4">
<p class="text-sm hidden md:block">
管理者:遅咲きエンジニア
</p>
<!-- ハンバーガーメニュー -->
<button
@click="menuOpen = !menuOpen"
class="md:hidden text-2xl"
>
☰
</button>
</div>
</header>
<!-- スマホ用メニュー -->
<div
x-show="menuOpen"
class="fixed top-0 right-0 z-40 w-64 h-screen bg-gray-700 text-white p-6 md:hidden shadow-lg"
>
<div class="flex justify-between items-center">
<p class="font-bold">
メニュー
</p>
<button
@click="menuOpen = false"
class="text-2xl"
>
×
</button>
</div>
<ul class="mt-6 space-y-3 text-sm">
<li class="px-2 py-1 rounded hover:bg-gray-600">ダッシュボード</li>
<li class="px-2 py-1 rounded hover:bg-gray-600">作品一覧</li>
<li class="px-2 py-1 rounded hover:bg-gray-600">レビュー管理</li>
</ul>
</div>
<!-- 詳細モーダル -->
<div
x-show="modalOpen"
class="fixed inset-0 z-50 bg-black/50 flex items-center justify-center p-4"
>
<div class="bg-white rounded-lg shadow-lg w-full max-w-md p-6 border">
<div class="flex justify-between items-center">
<h3 class="text-lg font-bold">
サンプル映画タイトル
</h3>
<button
@click="modalOpen = false"
class="text-2xl text-gray-500 hover:text-gray-800"
>
×
</button>
</div>
<div class="mt-4 space-y-2 text-sm text-gray-700">
<p>
平均評価:4.2
</p>
<p>
レビュー数:12件
</p>
<p>
ここに作品の詳細情報を表示します。
</p>
</div>
<div class="mt-6 text-right">
<button
@click="modalOpen = false"
class="px-3 py-1.5 text-sm border border-gray-300 text-gray-700 rounded hover:bg-gray-200"
>
閉じる
</button>
</div>
</div>
</div>
<main class="flex flex-col md:flex-row items-start">
<aside class="hidden md:block md:w-48 bg-gray-600 text-white p-4 md:min-h-screen">
<!-- サイドバー -->
<p class="font-bold">
サイドバー
</p>
<ul class="mt-4 space-y-2 text-sm">
<li class="px-2 py-1 rounded hover:bg-gray-500">ダッシュボード</li>
<li class="px-2 py-1 rounded hover:bg-gray-500">作品一覧</li>
<li class="px-2 py-1 rounded hover:bg-gray-500">レビュー管理</li>
</ul>
</aside>
<div class="w-full flex-1 p-6 bg-gray-100 min-h-screen">
<h2 class="text-lg font-bold">
作品管理
</h2>
<p class="text-sm text-gray-600 mt-1">
登録済み作品の確認・編集・削除を行います。
</p>
<div class="hidden md:block bg-white border rounded-lg shadow-sm mt-6">
<table class="w-full text-sm">
<!-- PC用テーブル -->
<thead class="bg-gray-700 text-white">
<tr>
<th class="px-4 py-2 text-center">ID</th>
<th class="px-4 py-2 text-center">サムネイル</th>
<th class="px-4 py-2 text-center">タイトル</th>
<th class="px-4 py-2 text-center">平均評価</th>
<th class="px-4 py-2 text-center">レビュー数</th>
<th class="px-4 py-2 text-center">操作</th>
</tr>
</thead>
<tbody>
<!-- 作品データ -->
<tr class="border-b">
<td class="px-4 py-2">1</td>
<td class="px-4 py-2">
<img
src="images/sample-poster.png"
alt="サンプル画像"
class="w-12 h-12 object-cover rounded border border-gray-300"
>
</td>
<td class="px-4 py-2">サンプル映画タイトル</td>
<td class="px-4 py-2">4.2</td>
<td class="px-4 py-2">12件</td>
<td class="px-4 py-2">
<div class="flex gap-2 justify-center">
<button
@click="modalOpen = true"
class="px-2 py-1 text-xs border border-gray-300 text-gray-700 rounded hover:bg-gray-200"
>
詳細
</button>
<button class="px-2 py-1 text-xs border border-blue-500 text-blue-600 rounded hover:bg-blue-100">
編集
</button>
<button class="px-2 py-1 text-xs border border-red-500 text-red-600 rounded hover:bg-red-100">
削除
</button>
</div>
</td>
</tr>
<tr class="border-b">
<td class="px-4 py-2">2</td>
<td class="px-4 py-2">
<img
src="images/sample-poster.png"
alt="サンプル画像"
class="w-12 h-12 object-cover rounded border border-gray-300"
>
</td>
<td class="px-4 py-2">サンプル映画タイトル2</td>
<td class="px-4 py-2">3.8</td>
<td class="px-4 py-2">8件</td>
<td class="px-4 py-2">
<div class="flex gap-2 justify-center">
<button
@click="modalOpen = true"
class="px-2 py-1 text-xs border border-gray-300 text-gray-700 rounded hover:bg-gray-200"
>
詳細
</button>
<button class="px-2 py-1 text-xs border border-blue-500 text-blue-600 rounded hover:bg-blue-100">
編集
</button>
<button class="px-2 py-1 text-xs border border-red-500 text-red-600 rounded hover:bg-red-100">
削除
</button>
</div>
</td>
</tr>
<tr class="border-b">
<td class="px-4 py-2">3</td>
<td class="px-4 py-2">
<img
src="images/sample-poster.png"
alt="サンプル画像"
class="w-12 h-12 object-cover rounded border border-gray-300"
>
</td>
<td class="px-4 py-2">サンプル映画タイトル3</td>
<td class="px-4 py-2">4.7</td>
<td class="px-4 py-2">20件</td>
<td class="px-4 py-2">
<div class="flex gap-2 justify-center">
<button
@click="modalOpen = true"
class="px-2 py-1 text-xs border border-gray-300 text-gray-700 rounded hover:bg-gray-200"
>
詳細
</button>
<button class="px-2 py-1 text-xs border border-blue-500 text-blue-600 rounded hover:bg-blue-100">
編集
</button>
<button class="px-2 py-1 text-xs border border-red-500 text-red-600 rounded hover:bg-red-100">
削除
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="md:hidden mt-6 space-y-4">
<div class="bg-white border rounded-lg shadow-sm p-4">
<!-- スマホ用カード -->
<div class="flex gap-3">
<img
src="images/sample-poster.png"
alt="サンプル画像"
class="w-16 h-16 object-cover rounded border border-gray-300"
>
<div class="flex-1">
<p class="font-bold">
サンプル映画タイトル
</p>
<p class="text-sm text-gray-600 mt-1">
平均評価:4.2 / レビュー数:12件
</p>
</div>
</div>
<div class="flex gap-2 mt-3">
<button
@click="modalOpen = true"
class="px-2 py-1 text-xs border border-gray-300 text-gray-700 rounded hover:bg-gray-200"
>
詳細
</button>
<button class="px-2 py-1 text-xs border border-blue-500 text-blue-600 rounded hover:bg-blue-100">
編集
</button>
<button class="px-2 py-1 text-xs border border-red-500 text-red-600 rounded hover:bg-red-100">
削除
</button>
</div>
</div>
<div class="bg-white border rounded-lg shadow-sm p-4">
<!-- スマホ用カード -->
<div class="flex gap-3">
<img
src="images/sample-poster.png"
alt="サンプル画像"
class="w-16 h-16 object-cover rounded border border-gray-300"
>
<div class="flex-1">
<p class="font-bold">
サンプル映画タイトル2
</p>
<p class="text-sm text-gray-600 mt-1">
平均評価:3.8 / レビュー数:8件
</p>
</div>
</div>
<div class="flex gap-2 mt-3">
<button
@click="modalOpen = true"
class="px-2 py-1 text-xs border border-gray-300 text-gray-700 rounded hover:bg-gray-200"
>
詳細
</button>
<button class="px-2 py-1 text-xs border border-blue-500 text-blue-600 rounded hover:bg-blue-100">
編集
</button>
<button class="px-2 py-1 text-xs border border-red-500 text-red-600 rounded hover:bg-red-100">
削除
</button>
</div>
</div>
<div class="bg-white border rounded-lg shadow-sm p-4">
<!-- スマホ用カード -->
<div class="flex gap-3">
<img
src="images/sample-poster.png"
alt="サンプル画像"
class="w-16 h-16 object-cover rounded border border-gray-300"
>
<div class="flex-1">
<p class="font-bold">
サンプル映画タイトル3
</p>
<p class="text-sm text-gray-600 mt-1">
平均評価:4.7 / レビュー数:20件
</p>
</div>
</div>
<div class="flex gap-2 mt-3">
<button
@click="modalOpen = true"
class="px-2 py-1 text-xs border border-gray-300 text-gray-700 rounded hover:bg-gray-200"
>
詳細
</button>
<button class="px-2 py-1 text-xs border border-blue-500 text-blue-600 rounded hover:bg-blue-100">
編集
</button>
<button class="px-2 py-1 text-xs border border-red-500 text-red-600 rounded hover:bg-red-100">
削除
</button>
</div>
</div>
</div>
</div>
</main>
</body>
</html>
今回追加したもの
| 追加したもの | 内容 |
|---|---|
@click="modalOpen = true" |
詳細ボタンを押したときにモーダルを開く |
modalOpen: false |
最初は詳細モーダルを閉じた状態にする |
x-show="modalOpen" |
modalOpen が true のときだけモーダルを表示する |
@click="modalOpen = false" |
閉じるボタンを押したときにモーダルを閉じる |
使ったTailwind CSSのclass
| class | 内容 |
|---|---|
fixed |
画面上に固定表示する |
inset-0 |
上下左右すべてを 0 にして画面全体に広げる |
z-50 |
ハンバーガーメニューより前面に表示する |
bg-black/50 |
黒背景を50%の透明度で表示する |
flex |
モーダル本体を中央配置しやすくする |
items-center |
要素を縦方向の中央に揃える |
justify-center |
モーダル本体を横方向の中央に配置する |
p-4 |
画面端とモーダルの間に余白を付ける |
bg-white |
モーダル本体の背景を白にする |
rounded-lg |
モーダル本体の角を丸くする |
shadow-lg |
モーダル本体に影を付ける |
w-full |
スマホ幅でも横幅を使いやすくする |
max-w-md |
モーダル本体の最大幅を決める |
border |
モーダル本体やボタンに枠線を付ける |
text-lg |
モーダルタイトルの文字を大きくする |
font-bold |
モーダルタイトルを太字にする |
justify-between |
タイトルと閉じるボタンを左右に配置する |
text-2xl |
閉じるボタンの文字サイズを大きくする |
text-gray-500 |
閉じるボタンの文字色をグレーにする |
hover:text-gray-800 |
hover時に閉じるボタンの文字色を濃くする |
mt-4 |
詳細情報の上に余白を付ける |
space-y-2 |
詳細情報の行間を空ける |
text-sm |
詳細情報や閉じるボタンの文字を少し小さくする |
text-gray-700 |
詳細情報の文字色を濃いグレーにする |
mt-6 |
下部の閉じるボタンの上に余白を付ける |
text-right |
下部の閉じるボタンを右寄せにする |
px-3 |
ボタンの左右に余白を付ける |
py-1.5 |
ボタンの上下に余白を付ける |
border-gray-300 |
ボタンの枠線を薄いグレーにする |
rounded |
ボタンの角を少し丸くする |
hover:bg-gray-200 |
hover時に薄いグレー背景にする |
表示確認
以下の点をブラウザで確認しました。
- 詳細ボタンをクリックするとモーダルが表示される
- モーダル背景が画面全体に表示される
- モーダル本体が中央に表示される
- 右上の「×」ボタンをクリックするとモーダルが閉じる
- 下部の「閉じる」ボタンをクリックするとモーダルが閉じる
- スマホ表示でも詳細モーダルが表示される
- PC表示でも詳細モーダルが表示される
- ハンバーガーメニューよりモーダルが前面に表示される
スマホ表示
PC表示
補足:z-indexの優先順位について
モーダルは、ユーザーに今操作してほしい内容を前面に出すUIです。
そのため、ハンバーガーメニューや通常の画面よりも、モーダルを前面に表示する必要があります。
実務では、z-index をその場の思いつきで大きくするのではなく、画面内の重なり順をあらかじめ決めておくことが多いです。
例えば、今回の管理画面UIでは以下のように考えます。
| レイヤー | 用途 |
|---|---|
| 指定なし | 通常コンテンツ |
z-30 |
固定ヘッダー |
z-40 |
スマホ用ハンバーガーメニュー |
z-50 |
モーダル背景・モーダル本体 |
z-[60] 以上 |
トースト通知や重要アラート |
z-index: 9999 のように極端に大きい値を使うと、あとから別のUIを重ねたいときに管理しづらくなります。
今回は、Day15で作ったハンバーガーメニューよりも、詳細モーダルを前面に出したいので、モーダルには z-50 を使います。
今日分かったこと
Day16では、詳細ボタンをクリックすると表示される詳細モーダルを作りました。
modalOpen: false でモーダルの開閉状態を用意し、@click="modalOpen = true" でモーダルを開けることが分かりました。
また、x-show="modalOpen" を使うことで、modalOpen が true のときだけモーダルを表示できました。
モーダル背景には fixed inset-0 bg-black/50 を使い、画面全体を半透明の背景で覆いました。
モーダル本体は flex items-center justify-center を使うことで、画面中央に配置できました。
Day15のハンバーガーメニューは z-40、Day16の詳細モーダルは z-50 にすることで、モーダルをより前面に表示できました。
PC用テーブルとスマホ用カードの両方に同じ @click を追加することで、どちらの表示でも詳細モーダルを開けるようになりました。
次回やること
【Tailwind CSS入門 Day17】削除確認モーダルを作る
シリーズ記事
- 【Tailwind CSS入門 Day1】管理画面の見出しを作る
- 【Tailwind CSS入門 Day2】カードUIの土台を作る
- 【Tailwind CSS入門 Day3】画像付きカードを作る
- 【Tailwind CSS入門 Day4】作品情報の文字を整える
- 【Tailwind CSS入門 Day5】管理画面風のボタンを作る
- 【Tailwind CSS入門 Day6】作品カードUIを完成させる
- 【Tailwind CSS入門 Day7】管理画面風ボタンを色分けする
- 【Tailwind CSS入門 Day8】管理画面ヘッダーを作る
- 【Tailwind CSS入門 Day9】PC用サイドバーを作る
- 【Tailwind CSS入門 Day10】PC管理画面レイアウトを作る
- 【Tailwind CSS入門 Day11】作品一覧テーブルを作る
- 【Tailwind CSS入門 Day12】テーブルの見た目を整える
- 【Tailwind CSS入門 Day13】レスポンシブ表示に切り替える
- 【Tailwind CSS入門 Day14】Alpine.jsの基礎を学ぶ
- 【Tailwind CSS入門 Day15】ハンバーガーメニューを作る
- 【Tailwind CSS入門 Day16】詳細モーダルを作る ← 今回

