はじめに 🌟
Label は地味な部品に見えますが、実際にはフォームや設定画面の理解しやすさを大きく左右します。
入力欄の名前が曖昧だったり、placeholder をラベル代わりに使っていたり、チェックボックスに二重のラベルを付けていたりすると、それだけで操作ミスや読み上げの分かりにくさにつながります。
Fluent UI 2 でも Label は単独の見出しではなく、コンポーネントやコンポーネント群に名前を与えるための部品として扱われています。
ただし、React 側と Fluent UI Blazor 側では、他の入力コンポーネントの作りがかなり違います。そのため、同じ「ラベル」でも、日常的な使い方はかなり変わります。
本記事では、まず Fluent UI 2 とは何かを短く整理し、そのうえでこれまでの Fluent UI 2 シリーズをすべて紹介します。
そのあとに、Fluent UI 2 の Label と Fluent UI Blazor 5 の Label / Field / 入力コンポーネントの Label API を比較し、特にアクセシビリティとコンテンツの書き方を中心に整理します。
参照した公式情報はこちらです。
今回のゴール ✅
- ✅ Fluent UI 2 における
Labelの役割を理解する - ✅ これまでの Fluent UI 2 シリーズ全体の流れを把握する
- ✅ Fluent UI 2 と Fluent UI Blazor 5 のラベル設計の違いを整理する
- ✅ 入力コンポーネントの違いが、ラベルの使い方をどう変えるか理解する
- ✅ アクセシビリティとコンテンツ設計の重要ポイントを実務に落とし込む
Fluent UI 2 とは
Fluent UI 2 は、Microsoft の Fluent 2 デザインシステムを Web UI に落とし込むためのコンポーネント群と設計指針です。
見た目をそろえるための部品集ではなく、情報の優先順位、操作の一貫性、支援技術での理解しやすさまで含めて体験を整えることが前提になっています。
そのため Label も、ただの見出しテキストではありません。
「この入力は何を意味するか」「この選択肢グループは何のためのものか」を短く正確に伝えるための土台です。
とくにフォーム周辺では、Label 単体だけを見ても理解しにくいことがあります。
Field、Checkbox、Switch、RadioGroup、Combobox、Select といった周辺コンポーネントが、どこまでラベルを内包しているかで実装の自然さが変わるからです。
これまでの Fluent UI 2 シリーズ一覧 🧭
本記事までの Fluent UI 2 シリーズは次のとおりです。
今回の Label は、このシリーズの中でも Field、Checkbox、Combobox、Dropdown と特につながりが強いテーマです。
つまり、単体で理解するよりも、「周辺コンポーネントがどこまでラベルを肩代わりしてくれるか」を一緒に見たほうが理解しやすい部品です。
Label は何をするコンポーネントか
Fluent UI 2 の公式ガイドでは、Label は component または group of components に名前を与えるものと説明されています。
つまり、input 1 つに名前を付ける場合だけでなく、複数の選択肢グループや関連情報のまとまりに見出しを与える場面も含みます。
また、フォーム入力であれば、先へ進む前に必須かどうかが分かるよう、アスタリスクで required を示します。
加えて、ラベルは disabled 状態も持てますし、長くなった場合は折り返され、省略されません。
ここで大事なのは、Label が「飾り」ではなく、利用者の判断材料だということです。
省略すると意味が欠けますし、placeholder で代用するとフォーカスや入力で消えてしまうため、名前として安定しません。
Fluent UI 2 の Label と Fluent UI Blazor 5 の比較
結論から言うと、両者の違いは React 側はラベルを外出ししやすく、Blazor 側は入力コンポーネントの中にラベル機能を内包しやすいことです。
そのため、React では Label 単体や Field を明示的に使う場面が多く、Blazor では FluentTextInput や FluentSelect などの Label パラメーターを直接使う場面が多くなります。
| 観点 | Fluent UI 2 の Label | Fluent UI Blazor 5 |
|---|---|---|
| 🧭 基本の役割 | コンポーネントやグループに名前を与える |
FluentLabel はラベル表示用。実務では各入力コンポーネントの Label や FluentField も多用する |
| 🧱 実装の中心 |
Label と Field を組み合わせて意味づけする |
FluentTextInput / FluentSelect / FluentCombobox / FluentCheckbox / FluentSwitch / FluentRadioGroup が Label を内包する |
| 📐 レイアウト | 基本は上、必要なら inline | 単体 FluentLabel は上配置が基本。入力コンポーネント側は LabelPosition と LabelWidth を持つ |
| ❗ 必須表示 | required アスタリスクで示す |
Required を各入力や FluentField に設定できる。FluentLabel 自体にも required 表示がある |
| 🚫 disabled | ラベルも disabled 状態を取れる |
FluentLabel と各入力コンポーネントの両方で disabled を扱える |
| 💬 検証 / 補足 | 単独 Label ではなく Field 側で扱うことが多い |
多くの入力が Message / MessageCondition / MessageState を内包する |
| 🎨 見た目の調整 | 内容と配置のガイドが中心 |
FluentLabel には Size / Weight / Tooltip などの見た目寄り API がある |
Field 記事との関係
ここは少し整理しておきたいところです。
Label の記事と Field の記事は似ていますが、役割は同じではありません。
-
Label: 名前そのものをどう付けるか -
Field: ラベル、補足、検証メッセージをどう束ねるか
フォーム入力の文脈では、React でも Blazor でも Field 系の考え方がかなり重要です。
ただし、その前提として「そもそもラベルは何を伝えるべきか」を押さえておかないと、Field を使っても中身の文言がぶれてしまいます。
他の入力コンポーネントの違いが、Label の使い方を変える
このテーマで一番重要なのはここです。
Label そのものの API を比べるだけでは、実務での違いは見えません。入力コンポーネント側の作りが違うからです。
| 場面 | Fluent UI 2 | Fluent UI Blazor 5 |
|---|---|---|
| 📝 Text input / Select / Combobox |
Label を単体で置くか、Field で入力と束ねる考え方が自然 |
FluentTextInput / FluentSelect / FluentCombobox 自体が Label / Required / Message を持つ |
| ☑️ Checkbox | 各 Checkbox のラベルを個別に持たせる。グループならグループ名も必要 |
FluentCheckbox 自体に Label がある。Blazor 公式でも Checkbox に Field のラベルを重ねないよう案内されている |
| 🔁 Switch | 即時反映なのでラベルが設定名として重要 |
FluentSwitch に Label があり、CheckedMessage / UncheckedMessage より Label 利用が推奨される |
| 🔘 RadioGroup | グループ全体のラベルと各選択肢のラベルを分けて考える |
FluentRadioGroup が Label を持ち、各項目の表示は RadioLabel などで与えられる |
| 🧩 ラベルを持たない部品 |
Label を単体で添える価値がある |
FluentField を使って ProgressBar のような unlabeled control に説明を足せる |
つまり、React 側は Label を外から与える発想が強く、Blazor 側は入力コンポーネントが Label を内包する発想が強いです。
この違いを理解しておくと、「Blazor にも Label コンポーネントがあるから 1:1 で対応するはず」と考えずに済みます。
使用法の違いをコードで見る
React 側では、単独の Label を入力と結び付けるか、Field にまとめる書き方が自然です。
import { Field, Input, Label, Checkbox } from "@fluentui/react-components";
export function ProfileForm() {
return (
<>
<Label htmlFor="display-name" required>
表示名
</Label>
<Input id="display-name" />
<Field label="プロジェクト名" required>
<Input />
</Field>
<Checkbox label="製品アップデートを受け取る" />
</>
);
}
一方で Blazor 側は、入力コンポーネントの Label パラメーターをそのまま使うことが多いです。
<FluentTextInput Label="表示名"
Required="true"
@bind-Value="@DisplayName" />
<FluentCheckbox Label="製品アップデートを受け取る"
@bind-Value="@ReceiveUpdates" />
<FluentField Label="更新間隔"
Message="分単位で入力してください">
<ChildContent>
<InputText @bind-Value="@RefreshInterval" />
</ChildContent>
</FluentField>
@code {
string DisplayName = "";
bool ReceiveUpdates;
string RefreshInterval = "";
}
この差は、単なる文法の違いではありません。
React は「ラベルと入力の関係を自分で組み立てる」感覚が強く、Blazor は「入力コンポーネントがその関係をある程度まとめて持っている」感覚が強いです。
レイアウト
Fluent UI 2 の公式ガイドでは、ラベルは基本的にコンポーネントの上に置くのが推奨です。
ただし、レイアウト上の都合があれば inline にしてもよいとされています。
ここで見落としやすいのが、長いラベルの扱いです。
Fluent UI 2 では、ラベルはコンテナー幅を超えると折り返され、truncate されません。これはかなり重要です。ラベルは名前なので、省略して意味が欠けると理解そのものが壊れるからです。
Blazor 側でも「上に置く」のが基本ですが、実務でのレイアウト調整は FluentLabel 単体よりも、各入力コンポーネントの LabelPosition や LabelWidth で行うことが多くなります。
つまり、React 側は Label 自体の配置ガイドが前に出やすく、Blazor 側は Field / Input API 側の配置オプションが前に出やすい、という違いがあります。
レイアウトの判断をまとめると次のようになります。
| 状況 | どう置くか | 理由 |
|---|---|---|
| 1 列フォームを上から読ませたい | 上に置く | もっとも読みやすく、視線移動が少ない |
| 密度が高く横幅が十分ある | inline も検討する | 情報密度を上げられる |
| ラベルが長い | 折り返す | 意味を欠かさないため |
| Checkbox / Switch のような選択部品 | 部品に近い位置へ置く | 何を切り替えるかを一目で分かるようにする |
アクセシビリティ ♿
ここが本題です。
Label は見た目が付いていればよいわけではなく、支援技術にも「その入力の名前」として伝わる必要があります。
1. placeholder をラベル代わりにしない
これは Fluent UI 2 の Usage ガイドでも明言されています。
placeholder はヒントであって、ラベルの代わりではありません。
placeholder をラベル代わりにすると、入力開始で消えたり、読み上げ順が不安定になったりして、何を入力する欄なのかが分かりにくくなります。
最低限、ラベルは常に見える場所に出しておくほうが安全です。
2. ラベルは入力とプログラム上でも結び付いている必要がある
視覚的に近くへ置いただけでは不十分です。
React で Label を単独で使うなら、htmlFor と入力の id を対応させるか、Field のように関連付けをまとめて扱うパターンを選ぶ必要があります。
Blazor 側では、この関連付けを standalone の FluentLabel だけに任せるより、FluentTextInput や FluentSelect などの Label パラメーター、または FluentField を使うほうが自然です。
特に Blazor の入力コンポーネントは、Label だけでなく Required、Message、MessageState まで一緒に扱えるため、支援技術向けの説明も一貫させやすいです。
Blazor でフォーム入力に名前を付けたいときは、まず各入力コンポーネントの Label か FluentField を検討したほうが安全です。
FluentLabel を見出しのように置くだけでは、フォームの意味づけが分散しやすくなります。
3. 1 つのラベルで 1 つの入力、または 1 つのグループを説明する
Fluent UI Blazor の Field ガイドでも、1 つの Field に複数コントロールを入れないよう案内されています。
これはラベルの対応先が曖昧になるからです。
一方で、Checkbox や RadioGroup のようなグループでは、グループ全体の名前と各項目の名前を分けて考える必要があります。
「通知方法」というグループ名があり、その下に「メール」「SMS」「プッシュ通知」が並ぶ、という形です。
4. disabled 状態では見た目のコントラスト要件が緩和される
Fluent UI 2 のガイドでは、disabled 状態のラベルはコントラスト要件を満たす必要がないとされています。
これは disabled な UI が WCAG 上の通常の操作対象とは扱いが異なるためです。
ただし、だからといって重要な説明を disabled ラベルの中へ隠してよいわけではありません。
「なぜ無効なのか」「どうすれば有効になるのか」の説明が必要なら、別の補足テキストで見えるようにしておくほうが親切です。
5. 関連する WCAG
Label の設計では、少なくとも次の達成基準を意識しておくと整理しやすいです。
要するに、見た目の近さだけで満足せず、名前として伝わるか、関係がコードでも表現されているかを確認することが重要です。
コンテンツの書き方 ✍️
Fluent UI 2 の Label Usage ガイドは、ここもかなり明確です。
ラベルは「何の情報を求めているか」を短く説明するためのもので、通常は短い句が最適です。
基本ルールは次のとおりです。
- 短く書く
- 説明文や手順文をラベルに入れすぎない
- 質問形式は必要なときだけ使う
- 英語では sentence-style capitalization を使う
- 質問でない限り文末の punctuation を付けない
- コロンを付けない
良い例 / 避けたい例
| 種類 | 例 | コメント |
|---|---|---|
| ✅ 良い例 | 表示名 |
何を入力するかが短く分かる |
| ✅ 良い例 | メールアドレス |
名詞句で自然 |
| ✅ 良い例 | 画像を表示する |
Switch や Checkbox のラベルとして意味が通る |
| ❌ 避けたい例 | ここに表示名を入力してください |
説明が長く、指示文に寄りすぎる |
| ❌ 避けたい例 | 表示名: |
コロンは不要 |
| ❌ 避けたい例 | メールを入力。 |
動作指示で、しかも句点が付いている |
日本語 UI では capitalization の影響はありませんが、考え方は同じです。
つまり、「入力欄の名前」として読める短い句にするのが基本です。たとえば「表示名」「メールアドレス」「通知を受け取る」のように、ラベルだけで意味が通るほうが安定します。
グループや選択肢の文言
Checkbox や RadioGroup のように複数項目が並ぶ場面では、共有語をグループ名側へ寄せると読みやすくなります。
| 書き方 | 例 |
|---|---|
| ✅ グループ名を立てる |
通知方法 の下に メール / SMS / プッシュ通知
|
| ✅ 平行構文をそろえる | すべて名詞、またはすべて動詞句にそろえる |
| ❌ 各項目へ同じ接頭語を繰り返す |
メール通知を受け取る / SMS 通知を受け取る / プッシュ通知を受け取る
|
Switch のような即時反映コンポーネントでは、Blazor 側のガイドでも短く具体的な設定名が推奨されています。
単なる オン / オフ よりも、画像を表示する、優先受信トレイを使う のように、その設定が何を変えるか分かる文言のほうが自然です。
まとめ 📝
Fluent UI 2 の Label は、単なる文字ではなく、入力やグループに名前を与えるための基礎部品です。
そのため、レイアウトや見た目だけでなく、アクセシビリティとコンテンツ設計まで含めて考える必要があります。
今回の比較で特に重要なのは次の 4 点です。
- React 側は
LabelやFieldを組み合わせてラベルを外から与える発想が強い - Blazor 側は各入力コンポーネントが
Label/Required/Messageを内包していることが多い - placeholder はラベルの代わりにならない
- ラベルは短く、意味が通り、支援技術にも名前として伝わる必要がある
Label は小さな部品ですが、ここが整うだけでフォーム全体の分かりやすさがかなり変わります。
Field や周辺入力コンポーネントの記事とあわせて読むと、設計のつながりがさらに見えやすくなるはずです。