Tailwind CSS インタラクティブ状態:hover/focus/active 状態プレフィックスとカーソルスタイル
状態プレフィックスの概要
Tailwindは状態プレフィックスを使用して、疑似クラスCSSを記述することなく、異なる状態の要素にスタイルを適用します。
| プレフィックス | CSS 疑似クラス | 説明 |
|---|---|---|
| hover: | :hover | マウスホバー |
| ocus: | :focus | フォーカス状態 |
| ctive: | :active | マウス押下 |
| disabled: | :disabled | 無効状態 |
| isited: | :visited | 訪問済みリンク |
| irst: | :first-child | 最初の子要素 |
| last: | :last-child | 最後の子要素 |
| odd: | :nth-child(odd) | 奇数の子要素 |
| even: | :nth-child(even) | 偶数の子要素 |
例
`html
hover 状態
<!-- focus 状態 -->
<div class="bg-white rounded-lg shadow p-6">
<h3 class="font-semibold mb-4">focus 状態</h3>
<div class="space-y-4">
<input type="text" placeholder="入力欄をクリックしてフォーカス効果を確認"
class="w-full p-3 border border-gray-300 rounded-lg focus:border-blue-500 focus:ring-2 focus:ring-blue-500/50 focus:outline-none transition-all">
<input type="text" placeholder="カスタムフォーカスシャドウ"
class="w-full p-3 border border-gray-300 rounded-lg focus:shadow-lg focus:shadow-purple-500/30 focus:border-purple-500 focus:outline-none transition-all">
</div>
</div>
<!-- active 状態 -->
<div class="bg-white rounded-lg shadow p-6">
<h3 class="font-semibold mb-4">active 状態</h3>
<div class="flex gap-4">
<button class="px-6 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600 active:bg-blue-800 active:scale-95 transition-all">
押下で暗く・縮小
</button>
<button class="px-6 py-3 bg-white border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 active:bg-gray-100 active:scale-95 transition-all">
押下エフェクト
</button>
</div>
</div>
<!-- disabled 状態 -->
<div class="bg-white rounded-lg shadow p-6">
<h3 class="font-semibold mb-4">disabled 状態</h3>
<div class="flex gap-4">
<button class="px-6 py-3 bg-blue-500 text-white rounded-lg disabled:opacity-50 disabled:cursor-not-allowed">
有効なボタン
</button>
<button disabled class="px-6 py-3 bg-blue-500 text-white rounded-lg disabled:opacity-50 disabled:cursor-not-allowed">
無効なボタン
</button>
<input type="text" placeholder="有効な入力欄"
class="p-3 border border-gray-300 rounded-lg disabled:bg-gray-100 disabled:cursor-not-allowed">
<input type="text" disabled placeholder="無効な入力欄"
class="p-3 border border-gray-300 rounded-lg disabled:bg-gray-100 disabled:cursor-not-allowed">
</div>
</div>
<!-- 訪問済みリンク -->
<div class="bg-white rounded-lg shadow p-6">
<h3 class="font-semibold mb-4">訪問済みリンク</h3>
<div class="flex gap-4">
<a href="#visited1" class="text-blue-600 hover:text-blue-800 visited:text-purple-600">
クリック後に紫色に
</a>
<a href="#visited2" class="text-green-600 hover:text-green-800 visited:text-gray-400">
クリック後に灰色に
</a>
</div>
</div>
従来のCSSとTailwindの比較 従来の方法では utton:hover { background-color: ... } のような疑似クラスルールを記述する必要がありますが、Tailwindでは hover:bg-blue-700 のようなプレフィックスで直接宣言できます。
構造的疑似クラス(first/last/odd/even)
構造的疑似クラスプレフィックスは、特定の位置にある子要素を選択するために使用します。
例
`html
first/last
- 最初のアイテム(first:bg-blue-50)
- 2番目のアイテム
- 3番目のアイテム
- 最後のアイテム(last:bg-green-50)
<!-- odd/even -->
<div class="bg-white rounded-lg shadow p-6">
<h3 class="font-semibold mb-4">odd/even</h3>
<ul class="space-y-0">
<li class="p-3 odd:bg-white even:bg-gray-50 border-b">行 1(odd:bg-white)</li>
<li class="p-3 odd:bg-white even:bg-gray-50 border-b">行 2(even:bg-gray-50)</li>
<li class="p-3 odd:bg-white even:bg-gray-50 border-b">行 3(odd:bg-white)</li>
<li class="p-3 odd:bg-white even:bg-gray-50 border-b">行 4(even:bg-gray-50)</li>
<li class="p-3 odd:bg-white even:bg-gray-50 border-b">行 5(odd:bg-white)</li>
<li class="p-3 odd:bg-white even:bg-gray-50">行 6(even:bg-gray-50)</li>
</ul>
</div>
<!-- テーブル例 -->
<div class="bg-white rounded-lg shadow p-6">
<h3 class="font-semibold mb-4">テーブルのしま模様</h3>
<table class="w-full">
<thead>
<tr class="bg-gray-100">
<th class="p-3 text-left">名前</th>
<th class="p-3 text-left">メール</th>
<th class="p-3 text-left">役割</th>
</tr>
</thead>
<tbody>
<tr class="odd:bg-white even:bg-gray-50 hover:bg-blue-50 transition-colors">
<td class="p-3">山田</td>
<td class="p-3">yamada@example.com</td>
<td class="p-3">管理者</td>
</tr>
<tr class="odd:bg-white even:bg-gray-50 hover:bg-blue-50 transition-colors">
<td class="p-3">鈴木</td>
<td class="p-3">suzuki@example.com</td>
<td class="p-3">編集者</td>
</tr>
<tr class="odd:bg-white even:bg-gray-50 hover:bg-blue-50 transition-colors">
<td class="p-3">佐藤</td>
<td class="p-3">sato@example.com</td>
<td class="p-3">ユーザー</td>
</tr>
<tr class="odd:bg-white even:bg-gray-50 hover:bg-blue-50 transition-colors">
<td class="p-3">田中</td>
<td class="p-3">tanaka@example.com</td>
<td class="p-3">ユーザー</td>
</tr>
</tbody>
</table>
</div>
従来のCSSとTailwindの比較 従来の方法では li:first-child { ... } や r:nth-child(even) { ... } のようなセレクターを記述する必要がありますが、Tailwindでは irst:bg-blue-50 や even:bg-gray-50 のようなプレフィックスで直接宣言できます。
group-hover と peer
group-hover: と peer は、親子要素間または兄弟要素間のインタラクティブ状態を処理するために使用します。
例
`html
group-hover 親子ホバー
デザインツール
親要素にホバーして効果を確認
パフォーマンス
親要素にホバーして効果を確認
セキュリティ
親要素にホバーして効果を確認
<!-- group 組み合わせ使用 -->
<div class="bg-white rounded-lg shadow p-6">
<h3 class="font-semibold mb-4">group 組み合わせ使用</h3>
<div class="space-y-4">
<div class="group flex items-center gap-4 p-4 bg-gray-50 rounded-lg hover:bg-blue-50 transition-colors cursor-pointer">
<div class="w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center group-hover:bg-blue-500 transition-colors">
<svg class="w-5 h-5 text-blue-500 group-hover:text-white transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</div>
<div class="flex-1">
<h4 class="font-medium group-hover:text-blue-600 transition-colors">メニュー項目 1</h4>
<p class="text-sm text-gray-500 group-hover:text-blue-400 transition-colors">説明テキスト</p>
</div>
<svg class="w-5 h-5 text-gray-400 group-hover:text-blue-500 group-hover:translate-x-1 transition-all" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</div>
<div class="group flex items-center gap-4 p-4 bg-gray-50 rounded-lg hover:bg-green-50 transition-colors cursor-pointer">
<div class="w-10 h-10 bg-green-100 rounded-full flex items-center justify-center group-hover:bg-green-500 transition-colors">
<svg class="w-5 h-5 text-green-500 group-hover:text-white transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</div>
<div class="flex-1">
<h4 class="font-medium group-hover:text-green-600 transition-colors">メニュー項目 2</h4>
<p class="text-sm text-gray-500 group-hover:text-green-400 transition-colors">説明テキスト</p>
</div>
<svg class="w-5 h-5 text-gray-400 group-hover:text-green-500 group-hover:translate-x-1 transition-all" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</div>
</div>
</div>
<!-- peer 兄弟要素 -->
<div class="bg-white rounded-lg shadow p-6">
<h3 class="font-semibold mb-4">peer 兄弟要素</h3>
<div class="space-y-4">
<div>
<input type="email" id="email" placeholder=" "
class="peer w-full p-3 pt-5 border border-gray-300 rounded-lg focus:border-blue-500 focus:ring-2 focus:ring-blue-500/50 focus:outline-none transition-all">
<label for="email"
class="absolute left-3 top-1 text-gray-400 text-sm transition-all peer-placeholder-shown:top-3.5 peer-placeholder-shown:text-base peer-focus:top-1 peer-focus:text-sm peer-focus:text-blue-500">
メールアドレス
</label>
</div>
<div class="relative">
<input type="password" id="password" placeholder=" "
class="peer w-full p-3 pt-5 border border-gray-300 rounded-lg focus:border-purple-500 focus:ring-2 focus:ring-purple-500/50 focus:outline-none transition-all">
<label for="password"
class="absolute left-3 top-1 text-gray-400 text-sm transition-all peer-placeholder-shown:top-3.5 peer-placeholder-shown:text-base peer-focus:top-1 peer-focus:text-sm peer-focus:text-purple-500">
パスワード
</label>
</div>
<div class="flex items-center gap-3">
<input type="checkbox" id="agree" class="peer sr-only">
<label for="agree"
class="w-5 h-5 border-2 border-gray-300 rounded peer-checked:bg-blue-500 peer-checked:border-blue-500 cursor-pointer transition-colors flex items-center justify-center">
<svg class="w-3 h-3 text-white opacity-0 peer-checked:opacity-100" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"></path>
</svg>
</label>
<span class="text-gray-700">利用規約に同意します</span>
</div>
</div>
</div>
カーソルスタイル(cursor-*)
cursor-* クラスは、マウスが要素の上にホバーしたときのカーソルスタイルを制御します。
| クラス | CSS 値 | 説明 |
|---|---|---|
| cursor-auto | cursor: auto | 自動(デフォルト) |
| cursor-default | cursor: default | デフォルト矢印 |
| cursor-pointer | cursor: pointer | 指のポインター |
| cursor-wait | cursor: wait | 待機 |
| cursor-text | cursor: text | テキスト選択 |
| cursor-move | cursor: move | 移動 |
| cursor-not-allowed | cursor: not-allowed | 禁止 |
| cursor-grab | cursor: grab | 掴む |
| cursor-grabbing | cursor: grabbing | 掴んでいる |
| cursor-crosshair | cursor: crosshair | 十字カーソル |
| cursor-zoom-in | cursor: zoom-in | ズームイン |
| cursor-zoom-out | cursor: zoom-out | ズームアウト |
例
`html
カーソルスタイル
従来のCSSとTailwindの比較 従来の方法では cursor: pointer のようなCSSプロパティを記述する必要がありますが、Tailwindでは cursor-pointer のようなクラス名で直接宣言できます。
選択制御(select-*)
select-* クラスは、ユーザーがテキストを選択できるかどうかを制御します。
| クラス | CSS 値 | 説明 |
|---|---|---|
| select-none | user-select: none | 選択不可 |
| select-text | user-select: text | 選択可能(デフォルト) |
| select-all | user-select: all | クリックで全選択 |
| select-auto | user-select: auto | 自動 |
例
`html
選択制御
select-none:選択不可
このテキストは選択できません。ボタンやラベルなどのインタラクティブ要素に適しています。
select-text:選択可能(デフォルト)
このテキストは選択できます。本文コンテンツに適しています。
select-all:クリックで全選択
const apiKey = "abc123";
<!-- 実践的応用 -->
<div class="bg-white rounded-lg shadow p-6">
<h3 class="font-semibold mb-4">実践的応用</h3>
<div class="space-y-4">
<!-- コードブロック -->
<div class="bg-gray-900 text-green-400 p-4 rounded-lg font-mono text-sm select-all">
npm install tailwindcss
</div>
<!-- ボタンテキストは選択不可 -->
<div class="flex gap-4">
<button class="px-6 py-3 bg-blue-500 text-white rounded-lg select-none cursor-pointer hover:bg-blue-600">
ボタンテキストは選択不可
</button>
<button class="px-6 py-3 bg-green-500 text-white rounded-lg select-none cursor-pointer hover:bg-green-600">
送信確認
</button>
</div>
</div>
</div>
リサイズ制御(resize-*)
esize-* クラスは、要素をリサイズできるかどうかを制御します。
| クラス | CSS 値 | 説明 |
|---|---|---|
| esize-none | ||
| esize: none | リサイズ不可 | |
| esize-y | ||
| esize: vertical | 垂直方向のみリサイズ | |
| esize-x | ||
| esize: horizontal | 水平方向のみリサイズ | |
| esize | ||
| esize: both | リサイズ可能 |
例
`html
リサイズ制御
resize-none:リサイズ不可
resize-y:垂直方向のみリサイズ
resize-x:水平方向のみリサイズ
resize:リサイズ可能
従来のCSSとTailwindの比較 従来の方法では esize: vertical のようなCSSプロパティを記述する必要がありますが、Tailwindでは esize-y のようなクラス名で直接宣言できます。
スクロール動作(scroll-*)
scroll-* クラスは、スクロール動作を制御します。
| クラス | CSS 値 | 説明 |
|---|---|---|
| scroll-auto | scroll-behavior: auto | 自動(デフォルト) |
| scroll-smooth | scroll-behavior: smooth | スムーズスクロール |
| snap-start | scroll-snap-align: start | 開始位置にスナップ |
| snap-center | scroll-snap-align: center | 中央にスナップ |
| snap-end | scroll-snap-align: end | 終了位置にスナップ |
| snap-none | scroll-snap-type: none | スナップなし |
| snap-x | scroll-snap-type: x mandatory | 水平スナップ |
| snap-y | scroll-snap-type: y mandatory | 垂直スナップ |
例
`html
<!-- スクロールスナップ -->
<div class="bg-white rounded-lg shadow p-6">
<h3 class="font-semibold mb-4">スクロールスナップ</h3>
<div class="flex overflow-x-auto snap-x snap-mandatory gap-4 pb-4">
<div class="snap-center flex-shrink-0 w-64 h-40 bg-blue-100 rounded-lg flex items-center justify-center">
<span class="text-blue-700 font-semibold">カード 1</span>
</div>
<div class="snap-center flex-shrink-0 w-64 h-40 bg-green-100 rounded-lg flex items-center justify-center">
<span class="text-green-700 font-semibold">カード 2</span>
</div>
<div class="snap-center flex-shrink-0 w-64 h-40 bg-purple-100 rounded-lg flex items-center justify-center">
<span class="text-purple-700 font-semibold">カード 3</span>
</div>
<div class="snap-center flex-shrink-0 w-64 h-40 bg-orange-100 rounded-lg flex items-center justify-center">
<span class="text-orange-700 font-semibold">カード 4</span>
</div>
<div class="snap-center flex-shrink-0 w-64 h-40 bg-red-100 rounded-lg flex items-center justify-center">
<span class="text-red-700 font-semibold">カード 5</span>
</div>
</div>
</div>
<!-- スクロールバー非表示 -->
<div class="bg-white rounded-lg shadow p-6">
<h3 class="font-semibold mb-4">スクロールバー非表示</h3>
<div class="flex overflow-x-auto scrollbar-hide gap-4 pb-4">
<div class="flex-shrink-0 w-48 h-32 bg-gradient-to-br from-blue-400 to-blue-600 rounded-lg flex items-center justify-center text-white">
スクロールバー非表示
</div>
<div class="flex-shrink-0 w-48 h-32 bg-gradient-to-br from-green-400 to-green-600 rounded-lg flex items-center justify-center text-white">
scrollbar-hide を使用
</div>
<div class="flex-shrink-0 w-48 h-32 bg-gradient-to-br from-purple-400 to-purple-600 rounded-lg flex items-center justify-center text-white">
水平スクロール可能
</div>
<div class="flex-shrink-0 w-48 h-32 bg-gradient-to-br from-orange-400 to-orange-600 rounded-lg flex items-center justify-center text-white">
続けてスクロール
</div>
</div>
</div>
❓ よくある質問
📖 まとめ
- hover:、ocus:、ctive:、disabled: などの状態プレフィックスで要素のインタラクティブ状態を制御
- irst:、last:、odd:、even: などの構造的疑似クラスで特定の子要素を選択
- group と group-hover: で親子要素間の連動ホバー効果を処理
- peer と peer-focus: で兄弟要素間の連動状態を処理
- cursor-* でカーソルスタイル、select-* でテキスト選択を制御
esize-* で要素のリサイズ、scroll-* でスクロール動作を制御
📝 課題
-
⭐ hover:、ocus:、ctive:、disabled: 状態プレフィックスを使用して、完全なインタラクティブ状態スタイリングを持つボタンコンポーネントを作成してください
-
⭐⭐ group と group-hover: を使用して、アイコン、テキスト、矢印が連動して変化するナビゲーションメニューを作成してください
-
⭐⭐⭐ peer と peer-focus: を使用してフローティングラベル効果を実装し、ocus: と invalid: 状態を組み合わせてフォームバリデーションスタイリングを実装するフォームを作成してください



