ユーザーからテキストを受け取るフォームの基本部品。入力前・中・後の全ステップで支援情報を提供することが品質の差になる。
この記事を読むと、ラベル設計・エラーフィードバック・状態実装の判断が自分でできるようになります。
1. UI例(Preview / Live)
実装で見る(GunjoUI)
この部品を、デザインシステム GUNJO の実装で確かめられます。
2. 定義(Definition)
ユーザーからテキスト(文字列・数値・パスワード等)を入力・編集・取得するためのフォーム部品。単一行の情報取得に特化し、長文は Textarea、選択肢から選ぶ場合は Select / Radio を使う。
3. 使い分け(When to use / When NOT to use)
3.1 When to use
- 名前・メールアドレス・検索キーワードなど、自由記述のテキストを求めるとき
- 単一行〜短い情報の入力を扱うとき
- ユーザーが入力する値が事前に定義できないとき
3.2 When NOT to use
- 選択肢が決まっている場合(Select / Radio を使う)
- 長文の自由記述(Textarea を使う)
- 数値のみ・範囲指定(
type="number"または Slider を検討)
3.3 代替UI(Alternatives)
- 選択肢から選ぶ →
Select/Radio - 長文入力 →
Textarea - 検索・候補表示 →
Combobox
4. 設計判断の核(Decision Principles)
入力前・入力中・入力後の全ステップでユーザーを支援する。
判断の優先順位:① ラベルを常時表示 → ② 適切な type / inputmode → ③ onBlurでバリデーション → ④ エラーは文章で伝える
- ラベルはプレースホルダーで代替しない(入力開始で消えるため)
- エラーは「何がダメか」「どう直すか」をセットで伝える
type属性はデータに合わせる(email / tel / password / number)- パスワードには表示/非表示トグルを用意する
5. 状態設計(States)
5.1 必須状態(Required)
- Default:ラベルと入力枠が明確。プレースホルダーで例示可
- Focus:フォーカスリングを明確に表示(省略不可)
- Error:枠を赤くし、エラーメッセージを枠の下に表示
- Disabled:全体をグレーアウト。
cursor-not-allowed
5.2 条件付き状態(Conditional)
- Hover:枠線を濃くしてインタラクティブであることを示す
- Filled:入力済みの値を表示。文字コントラスト確保
- Read-only:コピー可・編集不可。Disabledと背景色で区別
5.3 State Gallery
| 状態 | 必須 | 何を伝えるか |
|---|---|---|
| Default | ✅ | 入力待ちであることを示す |
| Focus | ✅ | 今ここに入力中であることを示す |
| Error | ✅ | 何が問題でどう直すかを伝える |
| Disabled | ✅ | 今は入力できないことを示す |
| Hover | — | 入力できることをマウスユーザーに示す |
| Filled | — | 入力済みの値を明確に表示する |
| Read-only | — | 表示専用であることを示す |
6. バリエーション設計(Variants)
type属性でセマンティクスを、見た目ではなくデータの種類で分ける。
| type | 用途 | モバイルキーボード |
|---|---|---|
| text | 汎用テキスト | 標準 |
| メールアドレス | @付きキーボード | |
| tel | 電話番号 | 数字パッド |
| password | パスワード | 伏せ字 |
| number | 数値 | 数字キーボード |
| search | 検索 | 検索キーボード |
禁止パターン:プレースホルダーをラベルの代わりに使う → 入力開始で文脈が消える
7. パターン集(Good / Bad / How to fix)
7.0 よく崩れる設計パターン(3つ)
- プレースホルダー依存:ラベルがなくプレースホルダーに項目名を書く → 入力開始で何の項目か分からなくなる
- 不親切なエラー:「エラーがあります」だけ → どこが・何が・どう直すか伝わらない
- type属性の無視:全フィールドを
type="text"にする → モバイルで適切なキーボードが出ない
7.1 Bad(典型3つ)
placeholder="メールアドレス"のみで<label>がない → 入力開始で何の欄か消える- エラー時に枠が赤くなるだけでメッセージがない → どう修正すればよいか分からない
- パスワード欄に表示トグルがない → 入力ミスに気づけない
7.2 Good(対になる3つ)
<label>を枠の上に常時表示し、プレースホルダーは入力例として補足するaria-invalid="true"+aria-errormessage+ 「@が含まれていません」のような具体的なメッセージ- パスワード欄に👁ボタンを配置し、
type="password"↔type="text"を切り替える
7.3 How to fix(手順)
- プレースホルダーに書かれた項目名を
<label>として枠の外に移動する <input>のtypeをデータの種類に合わせて設定する- バリデーションエラーのメッセージを「何がダメか」「どう直すか」の形に書き直す
aria-invalidとaria-errormessage/aria-describedbyを追加する
7.4 GUNJO 実装で見る(Bad / Good)
同じ GUNJO の Input を、エラー表現の崩れた使い方と正しい使い方で対比。
8. ルール(Must / Better)
Must(守らないと壊れる)
Better(品質が跳ねる)
9. アクセシビリティ要件(必須)
Keyboard
Tabでフォーカスでき、入力中に意図せずフォーカスが他へ移動しないこと
Focus
- フォーカスリングは周囲の要素と4.5:1以上のコントラスト比を持つこと
Screen Reader
<label for="id">と<input id="id">を紐付け、フォーカス時に項目名が読み上げられること- エラー時は
aria-invalid="true"とaria-describedbyでエラーメッセージを関連付ける
<label for="email">メールアドレス</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email-error" />
<p id="email-error">@が含まれていません</p>
Touch / Pointer
- 入力エリアの高さは44px以上を確保する
Contrast / Readability
- 入力テキストと背景のコントラスト比は4.5:1以上にする
10. 実装メモ(Implementation Notes)
type="number"はブラウザごとに挙動差があるため、数値のみ許可したい場合はtype="text"+inputmode="numeric"+pattern="[0-9]*"の組み合わせが安定- Reactでエラー表示を
useStateで管理する場合、送信時だけでなくonBlurでもtouchedフラグを立てる - Disabledと Read-onlyは見た目を明確に区別する(Disabledは
opacity-50、Read-onlyはbg-muted)
11. 関連リンク
- 関連するUIデザイン原則: フィードバック (Feedback), アフォーダンス (Affordance)
- 用語集(定義): アクセシビリティ (Accessibility)
- 関連するUIコンポーネント(横): Textarea(テキストエリア), Select(セレクト / プルダウンメニュー), Checkbox(チェックボックス)
まとめ
Text Inputの品質は「ラベルの有無」「エラーの具体性」「type属性の正確さ」の3点でほぼ決まります。迷ったら 4. 設計判断の核 に戻り、入力前・中・後の全ステップで支援情報が揃っているか確認してください。