Tailwind CSS で Form UI をデザイン:input, select, button のスタイリング事例集

Web アプリケーションの心臓部とも言えるフォーム要素は、ユーザーとプロダクトの最初の接点となることが多く、その品質がユーザー体験全体を左右する重要な要素です。美しく使いやすいフォームを実装することは、単なる見た目の問題ではなく、コンバージョン率やユーザー満足度に直結する重要な投資と言えるでしょう。しかし、従来の CSS 実装では、ブラウザ固有のスタイルリセットから始まり、一貫性のあるデザインシステムの構築まで、多くの煩雑な作業が必要でした。Tailwind CSS の登場により、これらの課題は大幅に改善され、効率的で保守性の高いフォーム実装が可能になっています。本記事では、input、select、button といった基本的なフォーム要素から、実践的なレイアウトパターンまで、明日からすぐに使える具体的なスタイリング事例を豊富にご紹介いたします。コピー&ペーストで活用できるコード例を中心に、フォーム UI デザインの実践的なノウハウをお伝えしていきます。
フォーム要素の基本デザイン原則
フォーム要素をデザインする際には、美しさだけでなくユーザビリティとアクセシビリティを両立させることが重要です。Tailwind CSS を活用する前に、まずは基本的なデザイン原則を確認しましょう。
一貫性のあるビジュアル階層
フォーム内の各要素は、その重要度と機能に応じて適切な視覚的重みを持つべきです。Tailwind CSS では、この階層を効率的に表現できます。
typescript// フォーム要素の重要度別スタイリング例
const FormHierarchy = {
primary:
'bg-blue-600 text-white font-semibold px-6 py-3 rounded-lg shadow-lg hover:bg-blue-700 transition-colors',
secondary:
'bg-gray-100 text-gray-700 font-medium px-5 py-2.5 rounded-md border border-gray-300 hover:bg-gray-50 transition-colors',
tertiary:
'text-blue-600 font-medium px-4 py-2 rounded hover:bg-blue-50 transition-colors',
input:
'border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent',
select:
'border border-gray-300 rounded-md px-3 py-2 pr-8 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent',
};
視認性とコントラストの確保
フォーム要素は、すべてのユーザーにとって読みやすく操作しやすくなければなりません。特に、文字色と背景色のコントラスト比は重要な要素です。
css/* 推奨されるコントラスト比の実現例 */
.form-input-high-contrast {
@apply bg-white text-gray-900 border-2 border-gray-400;
@apply focus:border-blue-600 focus:ring-4 focus:ring-blue-100;
}
.form-label-accessible {
@apply text-gray-800 font-medium text-sm mb-2 block;
}
.form-error {
@apply text-red-700 bg-red-50 border border-red-200 rounded-md px-3 py-2;
}
状態の明確な表現
フォーム要素の現在の状態(通常、フォーカス、エラー、無効化など)を明確に表現することで、ユーザーの操作性を向上させます。
状態 | 目的 | Tailwind クラス例 |
---|---|---|
デフォルト | 通常時の見た目を提供 | border-gray-300 bg-white text-gray-900 |
フォーカス | 入力中であることを示す | focus:border-blue-500 focus:ring-2 focus:ring-blue-200 |
エラー | 入力内容に問題があることを示す | border-red-500 bg-red-50 text-red-900 |
成功 | 正常な入力であることを示す | border-green-500 bg-green-50 text-green-900 |
無効化 | 操作できないことを示す | bg-gray-100 text-gray-500 cursor-not-allowed |
レスポンシブ対応の基本方針
モバイルファーストのアプローチを採用し、小さな画面でも操作しやすいフォーム設計を心がけます。
html<!-- レスポンシブなフォーム基本構造 -->
<form class="w-full max-w-lg mx-auto p-4 sm:p-6 lg:p-8">
<div class="space-y-4 sm:space-y-6">
<!-- フォーム要素がここに入る -->
</div>
</form>
アクセシビリティを考慮した設計
スクリーンリーダーやキーボード操作への対応を標準として組み込みます。
html<!-- アクセシブルなフォーム要素の例 -->
<div class="space-y-2">
<label
for="email"
class="block text-sm font-medium text-gray-700"
>
メールアドレス
<span class="text-red-500 ml-1" aria-label="必須"
>*</span
>
</label>
<input
type="email"
id="email"
name="email"
required
aria-describedby="email-error"
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
<p
id="email-error"
class="text-sm text-red-600"
role="alert"
>
<!-- エラーメッセージがここに表示される -->
</p>
</div>
Input 要素の多様なスタイリングパターン
Input 要素は最も使用頻度の高いフォーム要素の一つです。用途やデザインシステムに応じて、様々なスタイリングパターンを使い分けることが重要です。
基本的なテキスト入力フィールド
最もシンプルでありながら、しっかりとしたユーザビリティを持つ基本パターンです。
html<!-- シンプルな基本スタイル -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
お名前
</label>
<input
type="text"
class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200"
placeholder="山田太郎"
/>
</div>
<!-- 角丸を強調したモダンスタイル -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
メールアドレス
</label>
<input
type="email"
class="block w-full px-4 py-3 border border-gray-200 rounded-xl bg-gray-50 focus:bg-white focus:outline-none focus:ring-4 focus:ring-blue-100 focus:border-blue-500 transition-all duration-300"
placeholder="example@email.com"
/>
</div>
アイコン付き入力フィールド
視覚的な理解を助け、プロフェッショナルな印象を与えるアイコン付きスタイルです。
html<!-- 左側アイコン付き -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
検索
</label>
<div class="relative">
<div
class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"
>
<svg
class="h-5 w-5 text-gray-400"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
</svg>
</div>
<input
type="text"
class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="キーワードを入力..."
/>
</div>
</div>
<!-- 右側アクションボタン付き -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
パスワード
</label>
<div class="relative">
<input
type="password"
id="password"
class="block w-full px-3 py-2 pr-10 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="••••••••"
/>
<button
type="button"
class="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-gray-600"
onclick="togglePassword()"
>
<svg
class="h-5 w-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
/>
</svg>
</button>
</div>
</div>
状態別スタイリング
エラー、成功、警告など、異なる状態を明確に表現するパターンです。
html<!-- エラー状態 -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
メールアドレス
</label>
<input
type="email"
class="block w-full px-3 py-2 border-2 border-red-500 rounded-md bg-red-50 text-red-900 placeholder-red-300 focus:outline-none focus:ring-4 focus:ring-red-100 focus:border-red-500"
placeholder="example@email.com"
value="invalid-email"
/>
<p class="text-sm text-red-600 flex items-center mt-1">
<svg
class="w-4 h-4 mr-1"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z"
clip-rule="evenodd"
/>
</svg>
正しいメールアドレスを入力してください
</p>
</div>
<!-- 成功状態 -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
ユーザー名
</label>
<input
type="text"
class="block w-full px-3 py-2 border-2 border-green-500 rounded-md bg-green-50 text-green-900 focus:outline-none focus:ring-4 focus:ring-green-100 focus:border-green-500"
value="username123"
/>
<p class="text-sm text-green-600 flex items-center mt-1">
<svg
class="w-4 h-4 mr-1"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clip-rule="evenodd"
/>
</svg>
このユーザー名は利用可能です
</p>
</div>
<!-- 無効化状態 -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-500">
読み取り専用フィールド
</label>
<input
type="text"
disabled
class="block w-full px-3 py-2 border border-gray-200 rounded-md bg-gray-100 text-gray-500 cursor-not-allowed"
value="編集できません"
/>
</div>
サイズバリエーション
異なるコンテキストで使用するためのサイズバリエーションを提供します。
html<!-- 小サイズ -->
<input
type="text"
class="block w-full px-2 py-1 text-sm border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-transparent"
placeholder="小サイズ"
/>
<!-- 標準サイズ -->
<input
type="text"
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="標準サイズ"
/>
<!-- 大サイズ -->
<input
type="text"
class="block w-full px-4 py-3 text-lg border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="大サイズ"
/>
特殊な Input 要素
数値入力、日付入力、ファイルアップロードなど、特殊な用途に対応したスタイリングです。
html<!-- 数値入力 -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
価格
</label>
<div class="relative">
<div
class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"
>
<span class="text-gray-500 sm:text-sm">¥</span>
</div>
<input
type="number"
class="block w-full pl-8 pr-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="1,000"
/>
</div>
</div>
<!-- ファイルアップロード -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
ファイルを選択
</label>
<div class="flex items-center justify-center w-full">
<label
class="flex flex-col items-center justify-center w-full h-32 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 transition-colors"
>
<div
class="flex flex-col items-center justify-center pt-5 pb-6"
>
<svg
class="w-8 h-8 mb-4 text-gray-500"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
/>
</svg>
<p class="mb-2 text-sm text-gray-500">
<span class="font-semibold"
>クリックしてアップロード</span
>
またはドラッグ&ドロップ
</p>
<p class="text-xs text-gray-500">
PNG, JPG, GIF (最大 10MB)
</p>
</div>
<input type="file" class="hidden" accept="image/*" />
</label>
</div>
</div>
これまでの内容で記事の導入部分と基本的な原則、Input 要素のパターンを作成いたしました。続いて残りのセクションを追加いたします。
Select 要素のカスタマイズ手法
Select 要素は、ブラウザのデフォルトスタイルが特に目立つ要素の一つです。Tailwind CSS を使用して、統一感のあるデザインを実現する方法をご紹介します。
基本的な Select スタイリング
デフォルトの Select スタイルを上書きし、カスタムデザインを適用します。
html<!-- 基本的なSelect -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
都道府県
</label>
<select
class="block w-full px-3 py-2 border border-gray-300 rounded-md bg-white focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent appearance-none"
>
<option value="">選択してください</option>
<option value="tokyo">東京都</option>
<option value="osaka">大阪府</option>
<option value="kyoto">京都府</option>
</select>
</div>
<!-- カスタムドロップダウンアイコン付き -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
カテゴリー
</label>
<div class="relative">
<select
class="block w-full px-3 py-2 pr-10 border border-gray-300 rounded-md bg-white focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent appearance-none"
>
<option value="">選択してください</option>
<option value="web">Web開発</option>
<option value="mobile">モバイル開発</option>
<option value="design">デザイン</option>
</select>
<div
class="absolute inset-y-0 right-0 flex items-center px-2 pointer-events-none"
>
<svg
class="w-5 h-5 text-gray-400"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 9l-7 7-7-7"
/>
</svg>
</div>
</div>
</div>
スタイルバリエーション
異なる見た目の Select スタイルを提供します。
html<!-- フラットデザイン -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
優先度
</label>
<div class="relative">
<select
class="block w-full px-4 py-3 border-0 border-b-2 border-gray-300 bg-transparent focus:outline-none focus:border-blue-500 appearance-none"
>
<option value="">選択してください</option>
<option value="high">高</option>
<option value="medium">中</option>
<option value="low">低</option>
</select>
<div
class="absolute inset-y-0 right-0 flex items-center px-2 pointer-events-none"
>
<svg
class="w-5 h-5 text-gray-400"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 9l-7 7-7-7"
/>
</svg>
</div>
</div>
</div>
<!-- 丸みを帯びたモダンスタイル -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
支払い方法
</label>
<div class="relative">
<select
class="block w-full px-4 py-3 border border-gray-200 rounded-xl bg-gray-50 focus:bg-white focus:outline-none focus:ring-4 focus:ring-blue-100 focus:border-blue-500 appearance-none transition-all duration-300"
>
<option value="">選択してください</option>
<option value="credit">クレジットカード</option>
<option value="bank">銀行振込</option>
<option value="paypal">PayPal</option>
</select>
<div
class="absolute inset-y-0 right-0 flex items-center px-4 pointer-events-none"
>
<svg
class="w-5 h-5 text-gray-400"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 9l-7 7-7-7"
/>
</svg>
</div>
</div>
</div>
マルチセレクト対応
複数選択可能な Select の実装例です。
html<!-- 基本的なマルチセレクト -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
スキル(複数選択可)
</label>
<select
multiple
class="block w-full px-3 py-2 border border-gray-300 rounded-md bg-white focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent h-32"
>
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="javascript">JavaScript</option>
<option value="react">React</option>
<option value="vue">Vue.js</option>
<option value="angular">Angular</option>
</select>
<p class="text-sm text-gray-500">
Ctrl/Cmd キーを押しながらクリックで複数選択
</p>
</div>
<!-- カスタムマルチセレクト(チェックボックス風) -->
<div class="space-y-2">
<label class="block text-sm font-medium text-gray-700">
興味のある分野
</label>
<div
class="border border-gray-300 rounded-md bg-white p-2 space-y-2 max-h-40 overflow-y-auto"
>
<label
class="flex items-center space-x-2 p-2 hover:bg-gray-50 rounded cursor-pointer"
>
<input
type="checkbox"
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
/>
<span class="text-sm">フロントエンド開発</span>
</label>
<label
class="flex items-center space-x-2 p-2 hover:bg-gray-50 rounded cursor-pointer"
>
<input
type="checkbox"
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
/>
<span class="text-sm">バックエンド開発</span>
</label>
<label
class="flex items-center space-x-2 p-2 hover:bg-gray-50 rounded cursor-pointer"
>
<input
type="checkbox"
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
/>
<span class="text-sm">UI/UXデザイン</span>
</label>
<label
class="flex items-center space-x-2 p-2 hover:bg-gray-50 rounded cursor-pointer"
>
<input
type="checkbox"
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
/>
<span class="text-sm">データベース設計</span>
</label>
</div>
</div>
Button 要素の用途別デザイン
Button 要素は、ユーザーのアクションを促す重要な要素です。用途や重要度に応じて、適切なスタイリングを適用することが重要です。
基本的な Button スタイル
プライマリ、セカンダリ、ターシャリの 3 段階の重要度に対応したボタンデザインです。
html<!-- プライマリボタン -->
<button
type="submit"
class="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200"
>
送信する
</button>
<!-- セカンダリボタン -->
<button
type="button"
class="inline-flex items-center px-6 py-3 border border-gray-300 text-base font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200"
>
キャンセル
</button>
<!-- ターシャリボタン -->
<button
type="button"
class="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-blue-600 bg-transparent hover:bg-blue-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200"
>
詳細を見る
</button>
サイズバリエーション
異なるコンテキストで使用するためのサイズバリエーションを提供します。
html<!-- 小サイズ -->
<button
class="inline-flex items-center px-3 py-1.5 border border-transparent text-sm font-medium rounded text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-blue-500"
>
保存
</button>
<!-- 標準サイズ -->
<button
class="inline-flex items-center px-4 py-2 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
>
送信
</button>
<!-- 大サイズ -->
<button
class="inline-flex items-center px-8 py-4 border border-transparent text-lg font-medium rounded-lg text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
>
今すぐ始める
</button>
<!-- 全幅 -->
<button
class="w-full flex justify-center items-center px-4 py-3 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
>
アカウントを作成
</button>
状態別スタイリング
ローディング、無効化、成功などの状態を表現するボタンデザインです。
html<!-- ローディング状態 -->
<button
disabled
class="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 opacity-75 cursor-not-allowed"
>
<svg
class="animate-spin -ml-1 mr-3 h-5 w-5 text-white"
fill="none"
viewBox="0 0 24 24"
>
<circle
class="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
stroke-width="4"
></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
処理中...
</button>
<!-- 無効化状態 -->
<button
disabled
class="inline-flex items-center px-6 py-3 border border-gray-300 text-base font-medium rounded-md text-gray-400 bg-gray-100 cursor-not-allowed"
>
送信不可
</button>
<!-- 成功状態 -->
<button
class="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500"
>
<svg
class="w-5 h-5 mr-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5 13l4 4L19 7"
/>
</svg>
完了
</button>
<!-- 危険な操作用 -->
<button
class="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
>
<svg
class="w-5 h-5 mr-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
/>
</svg>
削除
</button>
アイコン付きボタン
視覚的な理解を助けるアイコン付きボタンのバリエーションです。
html<!-- 左アイコン -->
<button
class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
>
<svg
class="w-4 h-4 mr-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 6v6m0 0v6m0-6h6m-6 0H6"
/>
</svg>
新規作成
</button>
<!-- 右アイコン -->
<button
class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
>
次へ進む
<svg
class="w-4 h-4 ml-2"
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"
/>
</svg>
</button>
<!-- アイコンのみ -->
<button
class="inline-flex items-center p-2 border border-transparent rounded-full text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
>
<svg
class="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"
/>
</svg>
<span class="sr-only">編集</span>
</button>
ボタングループ
関連するアクションをグループ化して表示するパターンです。
html<!-- 水平ボタングループ -->
<div class="inline-flex rounded-md shadow-sm" role="group">
<button
type="button"
class="px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-l-lg hover:bg-gray-100 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700"
>
保存
</button>
<button
type="button"
class="px-4 py-2 text-sm font-medium text-gray-900 bg-white border-t border-b border-gray-200 hover:bg-gray-100 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700"
>
プレビュー
</button>
<button
type="button"
class="px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-r-lg hover:bg-gray-100 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700"
>
公開
</button>
</div>
<!-- 垂直ボタングループ -->
<div
class="inline-flex flex-col rounded-md shadow-sm"
role="group"
>
<button
type="button"
class="px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-t-lg hover:bg-gray-100 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700"
>
編集
</button>
<button
type="button"
class="px-4 py-2 text-sm font-medium text-gray-900 bg-white border-l border-r border-gray-200 hover:bg-gray-100 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700"
>
複製
</button>
<button
type="button"
class="px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-b-lg hover:bg-gray-100 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700"
>
削除
</button>
</div>
実用的なフォームレイアウト事例集
これまでご紹介した個別の要素を組み合わせて、実際のプロジェクトですぐに活用できる完成度の高いフォームレイアウトをご紹介いたします。
基本的な登録フォーム
シンプルで使いやすい会員登録フォームの実装例です。
html<div
class="max-w-md mx-auto bg-white rounded-lg shadow-md p-6"
>
<h2
class="text-2xl font-bold text-gray-900 mb-6 text-center"
>
アカウント作成
</h2>
<form class="space-y-4">
<!-- お名前 -->
<div>
<label
for="name"
class="block text-sm font-medium text-gray-700 mb-1"
>
お名前 <span class="text-red-500">*</span>
</label>
<input
type="text"
id="name"
name="name"
required
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200"
placeholder="山田太郎"
/>
</div>
<!-- メールアドレス -->
<div>
<label
for="email"
class="block text-sm font-medium text-gray-700 mb-1"
>
メールアドレス <span class="text-red-500">*</span>
</label>
<input
type="email"
id="email"
name="email"
required
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200"
placeholder="example@email.com"
/>
</div>
<!-- パスワード -->
<div>
<label
for="password"
class="block text-sm font-medium text-gray-700 mb-1"
>
パスワード <span class="text-red-500">*</span>
</label>
<input
type="password"
id="password"
name="password"
required
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200"
placeholder="••••••••"
/>
<p class="text-xs text-gray-500 mt-1">
8文字以上で英数字を含む
</p>
</div>
<!-- 利用規約への同意 -->
<div class="flex items-start space-x-2">
<input
type="checkbox"
id="terms"
name="terms"
required
class="mt-1 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
/>
<label for="terms" class="text-sm text-gray-700">
<a
href="#"
class="text-blue-600 hover:text-blue-800"
>利用規約</a
>
および
<a
href="#"
class="text-blue-600 hover:text-blue-800"
>プライバシーポリシー</a
>
に同意します
</label>
</div>
<!-- 送信ボタン -->
<button
type="submit"
class="w-full bg-blue-600 text-white py-3 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors duration-200 font-medium"
>
アカウントを作成
</button>
</form>
<p class="text-center text-sm text-gray-600 mt-4">
すでにアカウントをお持ちですか?
<a
href="#"
class="text-blue-600 hover:text-blue-800 font-medium"
>ログイン</a
>
</p>
</div>
お問い合わせフォーム
企業サイトでよく使用される、詳細な情報収集が可能なフォームです。
html<div
class="max-w-2xl mx-auto bg-white rounded-lg shadow-lg p-8"
>
<h2 class="text-3xl font-bold text-gray-900 mb-2">
お問い合わせ
</h2>
<p class="text-gray-600 mb-6">
お気軽にお問い合わせください。3営業日以内にご回答いたします。
</p>
<form class="space-y-6">
<!-- 基本情報セクション -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label
for="firstName"
class="block text-sm font-medium text-gray-700 mb-1"
>
姓 <span class="text-red-500">*</span>
</label>
<input
type="text"
id="firstName"
name="firstName"
required
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="山田"
/>
</div>
<div>
<label
for="lastName"
class="block text-sm font-medium text-gray-700 mb-1"
>
名 <span class="text-red-500">*</span>
</label>
<input
type="text"
id="lastName"
name="lastName"
required
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="太郎"
/>
</div>
</div>
<!-- 会社情報 -->
<div>
<label
for="company"
class="block text-sm font-medium text-gray-700 mb-1"
>
会社名・組織名
</label>
<input
type="text"
id="company"
name="company"
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="株式会社サンプル"
/>
</div>
<!-- 連絡先情報 -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label
for="email"
class="block text-sm font-medium text-gray-700 mb-1"
>
メールアドレス <span class="text-red-500">*</span>
</label>
<input
type="email"
id="email"
name="email"
required
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="example@email.com"
/>
</div>
<div>
<label
for="phone"
class="block text-sm font-medium text-gray-700 mb-1"
>
電話番号
</label>
<input
type="tel"
id="phone"
name="phone"
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="03-1234-5678"
/>
</div>
</div>
<!-- お問い合わせ種別 -->
<div>
<label
for="inquiryType"
class="block text-sm font-medium text-gray-700 mb-1"
>
お問い合わせ種別 <span class="text-red-500">*</span>
</label>
<div class="relative">
<select
id="inquiryType"
name="inquiryType"
required
class="block w-full px-3 py-2 pr-10 border border-gray-300 rounded-md bg-white focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent appearance-none"
>
<option value="">選択してください</option>
<option value="general">
一般的なお問い合わせ
</option>
<option value="support">サポート</option>
<option value="sales">
営業・サービスについて
</option>
<option value="partnership">
パートナーシップ
</option>
<option value="other">その他</option>
</select>
<div
class="absolute inset-y-0 right-0 flex items-center px-2 pointer-events-none"
>
<svg
class="w-5 h-5 text-gray-400"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 9l-7 7-7-7"
/>
</svg>
</div>
</div>
</div>
<!-- メッセージ -->
<div>
<label
for="message"
class="block text-sm font-medium text-gray-700 mb-1"
>
お問い合わせ内容 <span class="text-red-500">*</span>
</label>
<textarea
id="message"
name="message"
rows="5"
required
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-vertical"
placeholder="お問い合わせ内容をご記入ください..."
></textarea>
<p class="text-sm text-gray-500 mt-1">
500文字以内でご記入ください
</p>
</div>
<!-- プライバシー同意 -->
<div class="flex items-start space-x-2">
<input
type="checkbox"
id="privacy"
name="privacy"
required
class="mt-1 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
/>
<label for="privacy" class="text-sm text-gray-700">
<a
href="#"
class="text-blue-600 hover:text-blue-800"
>プライバシーポリシー</a
>
に同意の上、送信します
</label>
</div>
<!-- 送信ボタン -->
<div class="pt-4">
<button
type="submit"
class="w-full md:w-auto bg-blue-600 text-white py-3 px-8 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors duration-200 font-medium"
>
送信する
</button>
</div>
</form>
</div>
サブスクリプション設定フォーム
複雑な設定項目を扱うエンタープライズ向けフォームの例です。
html<div
class="max-w-4xl mx-auto bg-white rounded-lg shadow-lg p-8"
>
<h2 class="text-3xl font-bold text-gray-900 mb-2">
プラン設定
</h2>
<p class="text-gray-600 mb-8">
ご利用用途に合わせてプランをカスタマイズできます
</p>
<form class="space-y-8">
<!-- プラン選択 -->
<div>
<h3 class="text-lg font-semibold text-gray-900 mb-4">
基本プラン
</h3>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<label class="relative">
<input
type="radio"
name="plan"
value="basic"
class="peer sr-only"
/>
<div
class="border-2 border-gray-200 rounded-lg p-6 cursor-pointer transition-all duration-200 peer-checked:border-blue-500 peer-checked:bg-blue-50"
>
<h4 class="text-lg font-semibold text-gray-900">
ベーシック
</h4>
<p class="text-gray-600 mt-1">個人利用向け</p>
<p
class="text-2xl font-bold text-gray-900 mt-4"
>
¥980<span class="text-sm font-normal"
>/月</span
>
</p>
<ul
class="text-sm text-gray-600 mt-4 space-y-1"
>
<li>✓ 基本機能</li>
<li>✓ メールサポート</li>
<li>✓ 1GB ストレージ</li>
</ul>
</div>
</label>
<label class="relative">
<input
type="radio"
name="plan"
value="pro"
class="peer sr-only"
/>
<div
class="border-2 border-gray-200 rounded-lg p-6 cursor-pointer transition-all duration-200 peer-checked:border-blue-500 peer-checked:bg-blue-50"
>
<div class="flex items-center justify-between">
<h4
class="text-lg font-semibold text-gray-900"
>
プロ
</h4>
<span
class="bg-blue-100 text-blue-800 text-xs font-medium px-2 py-1 rounded"
>人気</span
>
</div>
<p class="text-gray-600 mt-1">
小規模チーム向け
</p>
<p
class="text-2xl font-bold text-gray-900 mt-4"
>
¥2,980<span class="text-sm font-normal"
>/月</span
>
</p>
<ul
class="text-sm text-gray-600 mt-4 space-y-1"
>
<li>✓ 全機能</li>
<li>✓ 電話サポート</li>
<li>✓ 10GB ストレージ</li>
<li>✓ チーム機能</li>
</ul>
</div>
</label>
<label class="relative">
<input
type="radio"
name="plan"
value="enterprise"
class="peer sr-only"
/>
<div
class="border-2 border-gray-200 rounded-lg p-6 cursor-pointer transition-all duration-200 peer-checked:border-blue-500 peer-checked:bg-blue-50"
>
<h4 class="text-lg font-semibold text-gray-900">
エンタープライズ
</h4>
<p class="text-gray-600 mt-1">大規模組織向け</p>
<p
class="text-2xl font-bold text-gray-900 mt-4"
>
お問い合わせ
</p>
<ul
class="text-sm text-gray-600 mt-4 space-y-1"
>
<li>✓ カスタム機能</li>
<li>✓ 専任サポート</li>
<li>✓ 無制限ストレージ</li>
<li>✓ SLA保証</li>
</ul>
</div>
</label>
</div>
</div>
<!-- オプション機能 -->
<div>
<h3 class="text-lg font-semibold text-gray-900 mb-4">
追加オプション
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="space-y-4">
<label
class="flex items-center justify-between p-4 border border-gray-200 rounded-lg cursor-pointer hover:bg-gray-50"
>
<div>
<h4 class="font-medium text-gray-900">
拡張ストレージ
</h4>
<p class="text-sm text-gray-600">
追加で50GB利用可能
</p>
</div>
<div class="flex items-center space-x-4">
<span class="font-semibold text-gray-900"
>+¥500/月</span
>
<input
type="checkbox"
name="options[]"
value="storage"
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
/>
</div>
</label>
<label
class="flex items-center justify-between p-4 border border-gray-200 rounded-lg cursor-pointer hover:bg-gray-50"
>
<div>
<h4 class="font-medium text-gray-900">
優先サポート
</h4>
<p class="text-sm text-gray-600">
24時間以内の回答保証
</p>
</div>
<div class="flex items-center space-x-4">
<span class="font-semibold text-gray-900"
>+¥1,000/月</span
>
<input
type="checkbox"
name="options[]"
value="support"
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
/>
</div>
</label>
</div>
<div class="space-y-4">
<label
class="flex items-center justify-between p-4 border border-gray-200 rounded-lg cursor-pointer hover:bg-gray-50"
>
<div>
<h4 class="font-medium text-gray-900">
API アクセス
</h4>
<p class="text-sm text-gray-600">
外部システム連携
</p>
</div>
<div class="flex items-center space-x-4">
<span class="font-semibold text-gray-900"
>+¥800/月</span
>
<input
type="checkbox"
name="options[]"
value="api"
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
/>
</div>
</label>
<label
class="flex items-center justify-between p-4 border border-gray-200 rounded-lg cursor-pointer hover:bg-gray-50"
>
<div>
<h4 class="font-medium text-gray-900">
カスタムブランディング
</h4>
<p class="text-sm text-gray-600">
ロゴとカラーのカスタマイズ
</p>
</div>
<div class="flex items-center space-x-4">
<span class="font-semibold text-gray-900"
>+¥1,500/月</span
>
<input
type="checkbox"
name="options[]"
value="branding"
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
/>
</div>
</label>
</div>
</div>
</div>
<!-- 支払い情報 -->
<div>
<h3 class="text-lg font-semibold text-gray-900 mb-4">
お支払い情報
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label
for="billingEmail"
class="block text-sm font-medium text-gray-700 mb-1"
>
請求先メールアドレス
</label>
<input
type="email"
id="billingEmail"
name="billingEmail"
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="billing@company.com"
/>
</div>
<div>
<label
for="billingCycle"
class="block text-sm font-medium text-gray-700 mb-1"
>
請求サイクル
</label>
<div class="relative">
<select
id="billingCycle"
name="billingCycle"
class="block w-full px-3 py-2 pr-10 border border-gray-300 rounded-md bg-white focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent appearance-none"
>
<option value="monthly">毎月請求</option>
<option value="yearly">
年間一括(10%割引)
</option>
</select>
<div
class="absolute inset-y-0 right-0 flex items-center px-2 pointer-events-none"
>
<svg
class="w-5 h-5 text-gray-400"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 9l-7 7-7-7"
/>
</svg>
</div>
</div>
</div>
</div>
</div>
<!-- 合計金額表示 -->
<div class="bg-gray-50 rounded-lg p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">
料金概要
</h3>
<div class="space-y-2">
<div class="flex justify-between text-sm">
<span class="text-gray-600">基本プラン</span>
<span class="text-gray-900">¥2,980/月</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-gray-600">オプション</span>
<span class="text-gray-900">¥1,500/月</span>
</div>
<hr class="my-2" />
<div
class="flex justify-between text-lg font-semibold"
>
<span class="text-gray-900">合計</span>
<span class="text-gray-900">¥4,480/月</span>
</div>
<p class="text-xs text-gray-500">
税別価格です。消費税が別途かかります。
</p>
</div>
</div>
<!-- 送信ボタン -->
<div class="flex flex-col sm:flex-row gap-4 pt-6">
<button
type="button"
class="px-6 py-3 border border-gray-300 text-gray-700 bg-white rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200 font-medium"
>
保存して後で続行
</button>
<button
type="submit"
class="px-8 py-3 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200 font-medium"
>
プランを開始
</button>
</div>
</form>
</div>
まとめ
本記事では、Tailwind CSS を活用したフォーム UI デザインの実践的な手法について、基本的な原則から具体的な実装例まで幅広くご紹介いたしました。
フォーム要素のスタイリングにおいて最も重要なのは、美しさと機能性の両立です。Tailwind CSS のユーティリティクラスを効果的に活用することで、保守性が高く、レスポンシブ対応もスムーズなフォーム実装が可能になります。特に、状態管理(フォーカス、エラー、成功など)を明確に表現することで、ユーザビリティの向上を実現できることがお分かりいただけたでしょう。
また、個別の要素スタイリングから完成度の高いフォームレイアウトまで、段階的にスキルアップできるよう構成いたしました。ご紹介したコード例は、そのままコピー&ペーストして活用していただけますが、プロジェクトの要件に応じてカスタマイズしていただくことで、より効果的なフォーム体験を提供できます。
現代の Web アプリケーションにおいて、フォームは単なるデータ入力インターフェースではなく、ユーザーとプロダクトの重要なタッチポイントです。適切なデザインシステムと一貫性のあるスタイリングにより、ユーザーの信頼感向上とコンバージョン率の改善を実現できるでしょう。
今後も新しいフォーム要素やインタラクションパターンが登場することが予想されますが、本記事で解説した基本原則と Tailwind CSS の柔軟性を活用することで、変化に対応しながら高品質なフォーム UI を継続的に提供していくことができるはずです。
ぜひ、実際のプロジェクトでこれらの手法をお試しいただき、より良いユーザー体験の実現にお役立てください。
関連リンク
- article
tailwind.config.js 完全ガイド:設定ファイルを使いこなして柔軟な拡張を
- article
Tailwind CSS で Form UI をデザイン:input, select, button のスタイリング事例集
- article
Tailwind と Figma 連携:デザイナーとの共同作業をスムーズにする方法
- article
Tailwind と CSS Modules は共存できる?両立パターンと使い分け
- article
Tailwind CSSでのダークモード対応するための実装手順と注意点
- article
Tailwind CSS でアニメーションをつける:motion-safe と keyframes の基本
- review
もう朝起きるのが辛くない!『スタンフォード式 最高の睡眠』西野精治著で学んだ、たった 90 分で人生が変わる睡眠革命
- review
もう「なんとなく」で決めない!『解像度を上げる』馬田隆明著で身につけた、曖昧思考を一瞬で明晰にする技術
- review
もう疲れ知らず!『最高の体調』鈴木祐著で手に入れた、一生モノの健康習慣術
- review
人生が激変!『苦しかったときの話をしようか』森岡毅著で発見した、本当に幸せなキャリアの築き方
- review
もう「何言ってるの?」とは言わせない!『バナナの魅力を 100 文字で伝えてください』柿内尚文著 で今日からあなたも伝え方の達人!
- review
もう時間に追われない!『エッセンシャル思考』グレッグ・マキューンで本当に重要なことを見抜く!