はじめに 🌟
Fluent UI 2 の Select は、フォームで使う「選ぶ」コンポーネントの中でもっともシンプルな部品です。
ブラウザーネイティブのスタイルで描画されるため、モバイルとの相性がよく、アクセシビリティ的にも安定しています。
この記事では、まず Fluent UI 2 とはどういうものかを整理し、これまでのシリーズを振り返ります。
そのうえで、Fluent UI 2 の Select に焦点を当て、同じ「選ぶ系」コンポーネントである Dropdown / Combobox / Field との使い分けを整理します。
さらに、Fluent UI Blazor 5 の FluentSelect との違い、Blazor 側の Autocomplete を含む近縁コンポーネントの比較も行います。
参考にした公式ページはこちらです。
- Fluent UI 2 Select usage
- Fluent UI 2 Dropdown usage
- Fluent UI 2 Combobox usage
- Fluent UI 2 Field usage
- Fluent UI Blazor 5 Select
- Fluent UI Blazor 5 Autocomplete
今回のゴール ✅
- ✅ Fluent UI 2 の
Selectの役割と適用場面を理解する - ✅
Dropdown/Combobox/Fieldとの違いと使い分けを整理する - ✅ Fluent UI Blazor 5 の
FluentSelectとの実装差を把握する - ✅ Blazor 5 の
Autocompleteを含む近縁コンポーネントを比較する - ✅ アクセシビリティとコンテンツ設計の要点を押さえる
Fluent UI 2 とは
Fluent UI 2 は、Microsoft の Fluent 2 デザインシステムを実装に落とし込むための UI コンポーネント群です。
単なる見た目のそろえ方ではなく、操作の一貫性・情報の意味づけ・支援技術での理解しやすさまでをまとめて設計するのが特徴です。
Select はこの中でも「標準的なフォーム選択」を担う部品です。
一見すれば普通のプルダウンですが、いつ使うか・なぜ使うかを公式ガイドが明確に定義しています。
それが Dropdown / Combobox との判断基準につながります。
これまでの Fluent UI 2 シリーズ一覧 🧭
本記事までのシリーズは次のとおりです。
今回の Select は、Dropdown / Combobox と並ぶ「選ぶ系」の中で、フォームの標準入力というポジションをはっきりと持っています。
シリーズを通して読むと、用途別に部品を選ぶ感覚が自然に身につきます。
Fluent UI 2 Select の基本
公式ガイドの要点を先にまとめます。
| 項目 | 内容 |
|---|---|
| 🧭 役割 | リストから 1 つを選ぶ標準フォームコンポーネント |
| 📋 選択肢数 | 少なくとも 4 個以上が前提 |
| 📱 向いている場面 | データ送信フォーム、モバイル向け UI |
| 🎨 スタイル | ブラウザーネイティブ |
| 🔀 代替検討 | スタイルや書式を制御したいなら Dropdown |
| ⌨️ 入力併用 | 自由入力や絞り込みが必要なら Combobox |
| 📝 Field との関係 | バリデーションやヘルパーテキストが必要なら Field でラップ |
A select lets people choose a single option from a list of at least four options. Selects use browser native styling for the listed options.
— Fluent UI 2 Select usage
Select は「とにかく選ばせる」ことに特化した、もっともシンプルな選択 UI です。
ネイティブの <select> に近い実装のため、OS やブラウザーのアクセシビリティ機能をそのまま活用できます。🖱️
デフォルト選択の動作
初回描画時は、リストの最初の選択肢がデフォルトで選択されます。
デフォルト値を変えたいときは、Select に defaultValue を渡すか、対応する <option> に selected を付けます。
import { Select } from "@fluentui/react-components";
export function PrioritySelect() {
return (
<Select defaultValue="medium">
<option value="low">Low</option>
<option value="medium">Medium</option>
<option value="high">High</option>
</Select>
);
}
Dropdown / Combobox / Field との使い分け
「選ぶ系」コンポーネントはどれも似ていますが、用途とトレードオフが異なります。
先に結論を整理します。
| コンポーネント | 向いている場面 | 入力 | スタイル制御 | 複数選択 |
|---|---|---|---|---|
| ✅ Select | 標準フォーム。モバイル重視 | なし | ブラウザー依存 | 基本なし |
| 🔽 Dropdown | カスタム表示。複数選択 | なし(タイプアヘッドのみ) | 自由 | あり |
| ⌨️ Combobox | 入力しながら絞り込む | あり | 自由 | あり |
| 📝 Field | ラベル・検証文をまとめる土台 | なし(他の入力を包む) | — | — |
Select
Select はブラウザーのネイティブ <select> 要素として機能します。
このため、スタイルはブラウザー・OS に依存します。
フォームとして送信することが目的で、モバイルユーザーが多い場面に向いています。
また、ネイティブ実装のため支援技術との相性も良好です。
Dropdown
Dropdown は選択 UI をカスタムレンダリングします。
選択肢にアイコンや補足情報を含めたいとき、複数選択が必要なとき、見た目を Fluent UI のデザインで統一したいときに適しています。
ただし、モバイルでは Select より使いにくくなる場合があります。
Combobox
Combobox は入力欄と候補リストの両方を持つ複合ウィジェットです。
候補が多く、テキスト入力で絞り込みたい場面や、候補にない値の自由入力を許したい場面に向きます。
詳しくは Fluent UI 2 の Combobox を理解する を参照してください。
Field
Field はコンポーネントそのものではなく、他の入力コンポーネントを包む土台です。
Select を Field でラップすることで、ラベル・ヒントテキスト・バリデーションメッセージを付けられます。
詳しくは Fluent UI 2 の Field を理解する を参照してください。
Field との組み合わせでも <option> を使います。
import { Field, Select } from "@fluentui/react-components";
export function StatusField() {
return (
<Field label="Status" required>
<Select>
<option value="open">Open</option>
<option value="in-progress">In progress</option>
<option value="done">Done</option>
</Select>
</Field>
);
}
Fluent UI Blazor 5 の近縁コンポーネント比較
Blazor 5 には React の Select に相当する FluentSelect があります。
あわせて、React Combobox に近い FluentCombobox、入力型の FluentAutocomplete も整理しておきます。
Fluent UI Blazor 5 の選択系コンポーネント
| コンポーネント | 主用途 | 入力 | 候補数 | アクセシビリティ |
|---|---|---|---|---|
| 🟢 FluentSelect | 標準フォーム選択(React Select 相当) | なし | 少〜中 | ◎ |
| 🔵 FluentCombobox | 入力+選択(React Combobox 相当) | あり | 中〜多 | ○ |
| 🟡 FluentAutocomplete | テキスト検索+選択 | あり | 多い | ⚠️(未実装部分あり) |
| 🟣 FluentListbox | 一覧から選択 | なし | 中 | ○ |
Blazor 5 には React の Dropdown(入力欄なしのカスタム選択 UI)に 1:1 で対応するコンポーネントはありません。
FluentCombobox は React の Combobox に近い「入力+選択」型です。
入力不要なリスト選択には FluentSelect / FluentListbox を使い分けてください。
FluentAutocomplete の位置づけ
FluentAutocomplete は候補が多い場合にとくに便利です。
OnOptionsSearch に非同期検索を実装することで、大量データも扱えます。
<FluentAutocomplete TOption="string"
Label="Assignee"
Placeholder="Search by name..."
OnOptionsSearch="@SearchOptions"
@bind-SelectedOptions="@SelectedItems" />
@code {
IEnumerable<string> SelectedItems = [];
private void SearchOptions(OptionsSearchEventArgs<string> e)
{
e.Items = AllMembers.Where(x =>
x.Contains(e.Text, StringComparison.OrdinalIgnoreCase));
}
static readonly string[] AllMembers =
["Alice", "Bob", "Carol", "Dave", "Eve"];
}
Blazor 5 の FluentAutocomplete は公式ドキュメントに Accessibility requirements are not yet implemented と記載があります。
アクセシビリティ要件が厳しい画面では、FluentSelect / FluentCombobox を先に検討してください。
Fluent UI 2 Select と Fluent UI Blazor 5 FluentSelect の違い
両者は同じ Fluent 2 の思想を共有していますが、実装レイヤーで大きな差があります。
| 観点 | Fluent UI 2(React) | Fluent UI Blazor 5 |
|---|---|---|
| 📦 コンポーネント名 |
Select + Option
|
FluentSelect<TOption, TValue> |
| 🧩 役割 | ブラウザーネイティブ選択 | Fluent UI ベースのリスト選択 |
| 🎨 スタイル | ブラウザー依存 | Fluent UI デザイントークン |
| 🔌 選択肢定義 | ネイティブ <option> を並べる |
Items + OptionText / 手動 FluentOption
|
| 📐 レイアウト |
Field でラップ |
Label / LabelPosition を内包 |
| ✅ 複数選択 | なし(複数は Dropdown / Combobox) |
Multiple="true" で有効 |
| ♿ アクセシビリティ | ネイティブ <select> ベース |
AriaLabel で補強 |
| 📵 ReadOnly | — | 非対応(Disabled で代替) |
| 🔢 サイズ変更 | — |
Size (Small / Medium / Large) |
| 🎨 外観変更 | — |
Appearance (Outline / FilledLighter / FilledDarker / Transparent) |
もっとも大きな差:スタイルの扱い
React 版の Select はあえてブラウザーネイティブのスタイルを使います。
モバイルでの使いやすさを最優先にしているためです。
一方、Blazor 版の FluentSelect は Fluent UI のデザイントークンでスタイリングされており、デスクトップ UI としての見た目の統一が図られています。
複数選択の差
React の Select は単一選択のみです。複数選択が必要なら Dropdown を使います。
一方、Blazor の FluentSelect は Multiple="true" で複数選択が可能です。
オプションのカスタマイズ
Blazor 版では OptionTemplate、OptionText、OptionValue、OptionDisabled を組み合わせることで、選択肢に豊富なカスタマイズができます。
FluentOption の Slot="@FluentSlot.Start" にアイコンやアバターを入れることもできます。
<FluentSelect TOption="string"
TValue="string"
Label="RGB Color"
Placeholder="Select a color"
@bind-Value="@Value">
<FluentOptionString Value="ff0000">Red</FluentOptionString>
<FluentOptionString Value="00ff00">Green</FluentOptionString>
<FluentOptionString Value="0000ff">Blue</FluentOptionString>
</FluentSelect>
@code {
string? Value;
}
Blazor 版の FluentSelect は ReadOnly に対応していません。
読み取り専用にしたい場合は Disabled="true" を使い、フォームの制御ロジックで対応してください。
ガイダンス・レイアウト・動作
いつ Select を使うか
公式ガイドでは、次の条件がそろうときに Select を選ぶよう案内しています。
- 選択肢が 4 個以上ある
- フォームとしてデータを送信する
- モバイルでの使いやすさを重視する
- 選択肢をリストから選ぶだけ(入力や絞り込みは不要)
逆に、次のどれかが必要なら代替コンポーネントを検討します。
- 選択肢の見た目をカスタムしたい →
Dropdown - 入力して絞り込みたい →
Combobox - 標準的なフォーム入力としてラベル+エラーをまとめて扱いたい →
Field+Select
3 つ以下の選択肢は RadioGroup を検討する
公式ガイドでは明示されていませんが、Fluent UI 全体のパターンとして、3 つ以下の選択肢では RadioGroup が推奨されます。
Select は「少なくとも 4 個」が前提です。
詳しくは Fluent UI 2 の Radio Group を理解する も参照してください。
レイアウト
Select は Field でラップしてレイアウトを整えるのが基本です。
ラベルの位置は Field の orientation で調整します(vertical がデフォルト、horizontal で横並び)。
Blazor 版では FluentSelect 自体に Label / LabelPosition / LabelWidth パラメーターがあるため、FluentField でラップしなくても使えます。
<FluentSelect Label="Language"
LabelPosition="@LabelPosition.Before"
LabelWidth="100px"
Items="@Languages"
@bind-Value="@Value" />
@code {
static string[] Languages = ["C#", "Java", "Python", "Go"];
string? Value;
}
動作:デフォルト選択
Select は初回描画時に最初の選択肢を自動選択します。
「何も選ばれていない」状態を表現したい場合は、空の選択肢またはプレースホルダー相当の選択肢を先頭に置きます。
<FluentSelect Label="Priority"
Placeholder="Select a priority"
Items="@Priorities"
@bind-Value="@Value" />
@code {
static string[] Priorities = ["None", "Low", "Medium", "High"];
string? Value;
}
アクセシビリティ ♿
Select に関するアクセシビリティの要点は、ネイティブの強みを活かすことと、ラベル設計にあります。
ネイティブ <select> のアクセシビリティ上の利点
React の Select はブラウザーネイティブの <select> として描画されます。
このため、次のアクセシビリティ機能がデフォルトで有効です。
- キーボード操作:Tab でフォーカス移動、矢印キーで選択肢を移動、Enter / Space で確定
- スクリーンリーダー:OS ネイティブの読み上げに対応(NVDA、VoiceOver、JAWS いずれも安定)
- モバイル支援技術:iOS VoiceOver / Android TalkBack でのスワイプ操作に対応
Blazor の FluentSelect はカスタム実装のため、ARIA ロール・状態の管理が必要になります。
AriaLabel を適切に設定することで、支援技術にコンポーネントの名前を伝えます。
<FluentSelect Label="Priority"
AriaLabel="タスクの優先度を選択してください"
Items="@Priorities"
@bind-Value="@Value" />
ラベルは必ず関連付ける
Select に対して、必ず関連するラベルを付けてください。
placeholder はラベルの代わりにはなりません。
フォーカスが当たると placeholder は消えてしまうため、入力の目的を伝える情報としては不十分です。
React では Field でラップすることでラベルが自動的に htmlFor で紐付きます。
Blazor では Label パラメーターを設定するか、aria-label 相当の AriaLabel を使います。
placeholder だけで入力の目的を説明するのはアクセシビリティ上の問題です。
WCAG 2.1 達成基準 1.3.1(情報及び関係性)および 3.3.2(ラベル又は説明)に影響します。
必ず label 要素またはそれに相当する属性で補完してください。
required と aria-required
必須フィールドを示す場合は、required / aria-required を設定します。
視覚的に * を表示するだけでなく、支援技術にも「必須」であることを伝えることが重要です。
<Field label="Country" required>
<Select>
<Option value="">Select a country</Option>
<Option value="jp">Japan</Option>
<Option value="us">United States</Option>
</Select>
</Field>
Disabled と ReadOnly
Disabled はユーザーの操作を完全に無効にします。
支援技術から操作できないだけでなく、フォーカスも受け付けません。
「閲覧はできる、操作はできない」という状態には注意が必要です。
Blazor の FluentSelect は ReadOnly を正式にサポートしていません。
公式ドキュメントに「ReadOnly attribute is not supported」と明記されています。
代わりに Disabled="true" を使いますが、disabled な要素はフォームの送信値に含まれないため、別途 hidden input などで値を保持する実装が必要です。
コンテンツ ✍️
Select のコンテンツ設計は、ラベルと選択肢の文言が中心です。
Fluent UI 2 公式ガイドに明確な指針があります。
ラベル
ラベルは、何を選ぶ欄かが一目で分かる説明的な名詞句にします。
単語または短いフレーズが最適です。
| 良い例 | 避けたい例 | 理由 |
|---|---|---|
| ✅ Country | ❌ Please select your country | 長すぎる |
| ✅ Priority | ❌ Priority level selection | 冗長 |
| ✅ Language | ❌ Choose language | ラベルに動詞は不要 |
選択肢の文言
公式ガイドの指針は 3 点です。
- 並列構造で書く(名詞なら名詞、動詞なら動詞)
- 先頭語の重複を避ける
- sentence-style capitalization(先頭語のみ大文字)
| 種類 | 例 | コメント |
|---|---|---|
| ❌ 重複する先頭語 |
Sort by date / Sort by name / Sort by priority
|
冗長で選びにくい |
| ✅ 並列構造 |
Date / Name / Priority
|
短く、比較しやすい |
| ✅ None を含む |
None / Open / In progress / Done
|
解除状態を明示 |
| ❌ 大文字乱用 |
Low Priority / High Priority
|
sentence-style ではない |
| ✅ 正しい大文字化 |
Low priority / High priority
|
先頭語のみ大文字 |
「None」の扱い
「何も選ばない」状態が意味を持つ場合は、None を選択肢に含めます。
これは「未選択」を明示的に表現するためのものであり、ユーザーが「選んでいない」状態を取り消せるようにします。
デフォルト選択が最初の項目になる Select では、None を先頭に置くとプレースホルダー的な役割を持たせられます。
placeholder はラベルの代わりではない
先述のとおり、placeholder はラベルの代替として使えません。
「Select a priority」のような文言を placeholder に入れるより、label でしっかり目的を伝えてください。
placeholder を使う場合は、書式の例示(例: 2024-01-01)など、補足的な情報に限ります。
実装例
React(Fluent UI 2)
import { Field, Select } from "@fluentui/react-components";
export function StatusForm() {
return (
<Field label="Status" required hint="Select the current status of this task.">
<Select defaultValue="open">
<option value="open">Open</option>
<option value="in-progress">In progress</option>
<option value="done">Done</option>
<option value="cancelled">Cancelled</option>
</Select>
</Field>
);
}
Blazor(Fluent UI Blazor 5)
<FluentSelect Label="Status"
Required="true"
Message="現在の状態を選択してください。"
Items="@Statuses"
@bind-Value="@Value" />
<div>Selected: @Value</div>
@code {
static string[] Statuses = ["Open", "In progress", "Done", "Cancelled"];
string? Value = "Open";
}
Blazor — カスタム選択肢(アイコン付き)
<FluentSelect TOption="string"
TValue="string"
Label="Priority"
@bind-Value="@Value">
<FluentOptionString Value="none">
<FluentIcon Value="@(new Icons.Regular.Size16.Line())" Slot="@FluentSlot.Start" />
None
</FluentOptionString>
<FluentOptionString Value="low">
<FluentIcon Value="@(new Icons.Regular.Size16.ArrowDown())" Slot="@FluentSlot.Start" />
Low
</FluentOptionString>
<FluentOptionString Value="high">
<FluentIcon Value="@(new Icons.Regular.Size16.ArrowUp())" Color="Color.Error" Slot="@FluentSlot.Start" />
High
</FluentOptionString>
</FluentSelect>
@code {
string? Value;
}
まとめ
Fluent UI 2 の Select を理解するうえでの要点は次のとおりです。
- 用途を絞る:フォームとして送信すること、モバイル互換、選択肢が 4 個以上のときが適切な使い時
- Dropdown / Combobox と役割を分ける:カスタム表示や複数選択は Dropdown、入力絞り込みは Combobox
- Field でラップしてラベルと紐づける:アクセシビリティのためにラベル関連付けは必須
- Blazor 版は機能が豊富:Appearance / Size / Multiple など React 版にない機能を持ち、OptionTemplate でカスタマイズも可能
-
AutoComplete は便利だがアクセシビリティに注意:
FluentAutocompleteはアクセシビリティ要件未実装の部分があるため、本番での扱いは慎重に
特にアクセシビリティとコンテンツ設計は、見た目調整より先に固めておくと、後から修正するより結果的に早くなります。
Select は小さなコンポーネントですが、正しく設計することで利用者の操作負荷を大きく下げられます。🚀