T-CREATOR

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

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 を継続的に提供していくことができるはずです。

ぜひ、実際のプロジェクトでこれらの手法をお試しいただき、より良いユーザー体験の実現にお役立てください。

関連リンク