はじめに 📝
テキストを複数行入力させたいとき、何も考えずに <textarea> を使っていませんか? Fluent UI 2 には、アクセシビリティ・デザイン・UX を統合した Textarea コンポーネントが用意されています。
この記事では、Textarea の役割と設計ガイダンス、Input との使い分け、アクセシビリティ実装の要点、Fluent UI Blazor 5 の FluentTextArea との比較、そして FluentTextInput(1 行入力)との使い分けをまとめます。Fluent UI 2 シリーズ第 38 回として、実装判断をすぐに活かせる形で整理します。
Fluent UI 2 とは 🎨
Fluent UI 2 は Microsoft が提供するデザインシステムです。React(v9 / converged components)を主軸に、Windows・Web・モバイルにわたって一貫した UX を実現します。アクセシビリティ(WCAG 2.1 AA 準拠基盤)、テーマ・トークン設計、コンポーザブルな API が特徴で、Microsoft 365 や Azure Portal など多くのプロダクトで採用されています。
Fluent UI 2 シリーズ一覧
本記事は第 38 回「Textarea」です。シリーズの全ラインナップは以下のとおりです。
Textarea とは — ガイダンスと役割
公式は Textarea をこう定義しています。
"A textarea allows people to enter long, free-form text data, like a comment."
つまり Textarea は、自由記述の長いテキストを入力させるためのコンポーネントです。コメント欄、お問い合わせフォームのメッセージ欄、プロフィールの自己紹介欄、バグ報告の再現手順など、ユーザーに複数行の文章を書いてもらう場面で活躍します。
一方、公式は「1 行の情報だけを入力させたい場合は Input を検討してください("If you only need someone to enter one line of information, try an input instead.")」とも明記しています。コンポーネントの選択は用途から始めるべきで、見た目だけで決めてはいけません。次の章で Input との違いを整理します。
Input との違い ✏️
用途の違い
| Input | Textarea | |
|---|---|---|
| 想定する入力量 | 1 行(短い) | 複数行(長い) |
| 代表的な用途 | 名前・メールアドレス・検索語・電話番号 | コメント・メッセージ・説明文・自己紹介 |
| 改行 | 不可 | 可 |
コンポーネントを選ぶ基準はシンプルです。「何行の情報を入力させたいか」 だけを考えてください。1 行なら Input、複数行なら Textarea です。
Input の詳細については、第 14 回「Input」の記事を参照してください。
コードサンプル
// Input(1行)
import { Input } from "@fluentui/react-components";
<Input placeholder="名前を入力" />
// Textarea(複数行)
import { Textarea } from "@fluentui/react-components";
<Textarea placeholder="コメントを入力" />
どちらも @fluentui/react-components からインポートしますが、コンポーネント名と適切な用途が異なります。プロダクトの要件を確認してから選択しましょう 🔍
動作(Behavior)
デフォルト動作
Textarea はデフォルトでリサイズ不可です。コンテンツが表示領域を超えた場合は、スクロールで対応します。
resize prop でリサイズを許可する
resize prop を使うと、ユーザーが手動でサイズを変更できるようになります。
| 値 | 動作 |
|---|---|
"none" |
リサイズ不可(デフォルト) |
"both" |
縦横両方向にリサイズ可能 |
"horizontal" |
横方向のみリサイズ可能 |
"vertical" |
縦方向のみリサイズ可能 |
<Textarea resize="vertical" placeholder="縦方向にリサイズ可能" />
多くのケースでは "vertical" が最も自然です。横方向のリサイズはレイアウトを崩しやすいため、特別な理由がない限り使わないほうが安全です。
レイアウト(Layout)
Textarea のサイズは、入力されると想定されるコンテンツ量に合わせて設計してください。小さすぎる入力欄はユーザーの書く気を削ぎ、大きすぎると他の要素を圧迫します。
- 短いコメント欄(SNS の返信欄など): 3〜4 行分
- お問い合わせのメッセージ欄: 5〜6 行分
- 詳細な説明文・報告書欄: 6〜8 行分
rows prop でデフォルトの高さを指定できます。
<Textarea rows={4} placeholder="コメントを入力してください" />
CSS で width を制御する場合は、コンテナに合わせて width: 100% を設定するのが一般的です。レイアウトとコンテンツ量の両方から適切な初期サイズを検討しましょう。
アクセシビリティ(Accessibility)♿
Textarea のアクセシビリティは特に重要です。実装を誤ると、支援技術のユーザーが入力欄の目的を理解できなくなります。以下の点を必ず押さえてください。
1. プレースホルダーだけに必須情報を入れてはいけない
プレースホルダーは値が入力されると消えます。認知障害のある人や短期記憶の弱い人は、入力中に「何を書くべきだったか」を忘れてしまいます。また、スクリーンリーダーによってはプレースホルダーを読まないケースもあります。
2. ラベルと組み合わせる
ラベルは常に画面に表示され続けるため、すべてのユーザーが入力欄の意図を確認できます。プレースホルダーを使う場合でも、必ずラベルと組み合わせることが必要です。
3. aria-label の付け方
プレースホルダーテキストには、支援技術向けの aria-label を関連付けます。これにより、スクリーンリーダーが入力欄の目的を正確にアナウンスします。
実装例
// ❌ 悪い例:ラベルなしのプレースホルダーのみ
<Textarea placeholder="メッセージを入力(必須)" />
// ✅ 良い例:ラベルと組み合わせる
import { Label, Textarea } from "@fluentui/react-components";
<Label htmlFor="message">メッセージ(必須)</Label>
<Textarea
id="message"
aria-label="メッセージ(必須)"
placeholder="例:ご意見やご要望をお書きください"
/>
4. Field コンポーネントとの連携(公式推奨パターン)
Field コンポーネントを使うと、ラベル・バリデーションメッセージ・ヒントテキストが自動でアクセシブルに関連付けられます。htmlFor や aria-describedby を手動で管理する必要がなくなるため、実装ミスを防げます。
import { Field, Textarea } from "@fluentui/react-components";
<Field label="メッセージ(必須)" required>
<Textarea placeholder="例:ご意見やご要望をお書きください" />
</Field>
特別な理由がない限り、Label を単独で使うよりも Field を使うパターンを推奨します 🌟
コンテンツ設計(Content)
適切なプレースホルダーテキストを書くことも、UX とアクセシビリティに直結します。
プレースホルダーテキストの適切な使い方
プレースホルダーは、入力値のフォーマット例や短い補足ヒントに留めてください。「何を書けばよいか」のイメージをユーザーに伝えるのが目的です。
- ✅ 「例:ご意見をお聞かせください」
- ✅ 「Type a new message」
- ✅ 「例:〇〇に関するご要望をお書きください」
プレースホルダーテキストにはピリオドを付けない
Microsoft Writing Style Guide に従い、プレースホルダーテキストはピリオドで終わらせません。文ではなく、短いフレーズとして書きましょう。
必須情報はラベルかヘルパーテキストに書く
プレースホルダーは消えますが、ラベルと Field の hint(ヘルパーテキスト)は常に表示されます。「必須」「最大文字数」「入力規則」のような情報は、必ずラベルかヘルパーテキストに書いてください。
// ✅ 良い例
import { Field, Textarea } from "@fluentui/react-components";
<Field label="フィードバック" hint="50〜500文字で入力してください">
<Textarea placeholder="例:使いやすさや改善点を教えてください" rows={4} />
</Field>
// ❌ 悪い例(プレースホルダーに必須情報)
<Textarea placeholder="フィードバックを入力(必須・50〜500文字)" />
プレースホルダーに情報を詰め込みすぎると、消えた瞬間にユーザーが途方に暮れます。シンプルに保ちましょう ✍️
ここまでは Fluent UI 2(React)の Textarea を取り上げました。続いて、同等機能を提供する Fluent UI Blazor 5 の FluentTextArea 実装と比較します。
Fluent UI Blazor 5 の FluentTextArea との比較
Fluent UI Blazor 5 にも同等の FluentTextArea コンポーネントがあります。React 版との機能対応を確認しながら、Blazor 独自の便利機能を紹介します。
参照: https://fluentui-blazor-v5.azurewebsites.net/TextArea
主要パラメーター
| パラメーター | 型 | 説明 |
|---|---|---|
Appearance |
TextAreaAppearance |
Outline / FilledLighter / FilledDarker / FilledLighterShadow / FilledDarkerShadow |
Size |
TextAreaSize |
Small / Medium / Large |
Resize |
TextAreaResize |
None / Both / Horizontal / Vertical(React の resize prop に相当) |
Width |
string |
幅の指定(例: "100%") |
Height |
string |
高さの指定(例: "80px") |
AutoResize |
bool |
入力内容に応じて高さを自動調整(Blazor 独自機能) |
Immediate |
bool |
入力中にリアルタイムでバインドを更新 |
ImmediateDelay |
int |
Immediate 時のデバウンス遅延(ミリ秒) |
ChangeAfterKeyPress |
KeyPress[]? |
発行するキー押下イベントを配列で指定(例:Enter / Ctrl+Enter)。チャット入力欄などに便利 |
Message |
string |
バリデーションメッセージのテキスト |
MessageState |
MessageState |
メッセージの種類(Error / Warning / Success) |
Blazor コードサンプル
@* 基本的な使い方 *@
<FluentTextArea @bind-Value="comment" Placeholder="コメントを入力してください" Height="100px" />
@* リサイズ可能 *@
<FluentTextArea @bind-Value="description" Resize="TextAreaResize.Vertical" Width="100%" />
@* AutoResize(Blazor 独自機能)*@
<FluentTextArea @bind-Value="message" AutoResize="true" Width="100%" />
@* チャット入力欄(Enter または Ctrl+Enter で送信) *@
<FluentTextArea @bind-Value="chatMessage"
ChangeAfterKeyPress="@([KeyPress.For(KeyCode.Enter).AndCtrlKey(), KeyPress.For(KeyCode.Enter)])"
OnChangeAfterKeyPress="@OnMessageSent"
Placeholder="メッセージを入力(Enter または Ctrl+Enter で送信)" />
@* バリデーションメッセージ付き *@
<FluentTextArea @bind-Value="feedback"
Label="フィードバック"
Placeholder="ご意見をお書きください"
Required="true"
Message="フィードバックを入力してください"
MessageState="MessageState.Error" />
AutoResize について
AutoResize="true" を設定すると、入力内容の行数に応じて textarea の高さが自動的に広がります。チャット画面や動的なフォームで特に便利です。React の Fluent UI 2 には直接対応する prop がないため、Blazor 版の独自優位点と言えます 🚀
ChangeAfterKeyPress について
ChangeAfterKeyPress に KeyPress.For(KeyCode.Enter) などを配列で渡すと、指定したキーが押されたタイミングで OnChangeAfterKeyPress イベントが発行されます。チャット送信欄のように「Enter で確定」する UX に非常に有用です。Immediate と組み合わせることで、さらに細かい入力イベント制御が可能です。
FluentTextInput(Input 相当)との比較
Blazor では 1 行テキスト入力に FluentTextInput を使います。FluentTextArea との違いを整理します。
| FluentTextInput | FluentTextArea | |
|---|---|---|
| 入力行数 | 1 行固定 | 複数行 |
Resize |
なし | あり(None / Both / Horizontal / Vertical) |
AutoResize |
なし | あり |
ChangeAfterKeyPress |
なし | あり |
| 主な用途 | 名前・メール・パスワード | コメント・メッセージ・説明文 |
@* 1行入力 *@
<FluentTextInput @bind-Value="name" Label="名前" Placeholder="例:山田 太郎" />
@* 複数行入力 *@
<FluentTextArea @bind-Value="bio" Label="自己紹介" Height="100px" Placeholder="例:〇〇エンジニアです" />
React 版と同様、「入力が 1 行か複数行か」という基準でコンポーネントを選択してください。
まとめ
- Textarea は長い自由記述テキストのためのコンポーネント。1 行の情報なら Input(React)/ FluentTextInput(Blazor)を使うのが正しい選択です
-
アクセシビリティの最重要点:プレースホルダーだけに頼らず、ラベルと
aria-labelを必ず組み合わせる。公式推奨のFieldコンポーネントを活用すれば、関連付けを自動で正しく設定できます ♿ - コンテンツ設計:プレースホルダーはフォーマット例に留め、必須情報はラベルかヘルパーテキストに書く。詰め込みすぎない
-
Fluent UI Blazor 5 は
AutoResizeやChangeAfterKeyPressなど、React 版にはない独自の便利な機能が充実しており、チャット UI や動的フォームで活躍します