近年お手本にしがちなデジタル庁の Design System では定義がされていませんでしたが、「チェックボックスの indeterminate 状態」について考えたところ、多分将来的に無くなるんだろうなと予想を立てました。
第三の状態: indeterminate
チェックボックスを使ったフォームが入れ子のとき、子が全て選択されていないことを示す表現として indeterminate が使われることがあります。
基本的にはチェックされているかいないかを表す checked 属性の true
false
を使いますが、別の属性として indeterminate (未決定状態)属性 の true
か false
があるため、トライステートとなります。
用例:ネストされたチェックボックス
例えば以下のように、絞り込み検索 UI などで、ネストされたチェックボックスの親子関係を作って、一括選択機能を提供するような場合に使用されることがあります。
ユーザー体験的には以下のような挙動が求められます。
- 子の一部がチェックされていて、全てはチェックされていない時は、親を indeterminate にする
- indeterminate またはチェックされていない状態の親を選択したら、子の全てをチェックする
- 全てチェックされていたら、全部チェック解除する
- 親-子-孫関係にある場合も、ルールは同じ
やや複雑で使いにくそうに感じる UI ですが、割とパソコンを日常使いしている方は慣れているかな?と思います。
しかしこの例で作った UI 、「興味のあるものをお答えください」という機能かと思いますが、なるべく広くオプトインしてもらいたい時に使う UI な気もして、闇の Web マーケティングの匂いを感じます。興味関心を選ばせるなら選択上限を設けたほうが最適なマッチングができますのにね。
Web での実装
Web ブラウザでは HTML タグではなく、JavaScript で設定できます。
checkboxElement.indeterminate = true
checked
属性は true
false
どちらかの値になり、null
など第 3 の値はないため、indeterminate
属性に true
false
をつけて実現します。
詳しい実装は以下のサイトが参考になります。
アクセシビリティ
ARIA では通常のチェックボックスの場合、チェックされているかどうかを示す aria-checked
属性 (Chrome Developer Tools のアクセシビリティタブでいう ON
プロパティ)は true
、チェックされていない時はは false
となりますが、 indeterminate
が true
な時は mixed
と表現されます。
indeterminate
が true
の場合、そのチェックボックスでは条件判定せず、子のチェックボックスを判定しにいくことになります。
まぁ実際、補助ツール使わなくてもそうですよね。
アプリケーションプラットフォームでの取り扱い
indeterminate
は Windows や macOS、Android でも標準的に搭載されているチェックボックス UI コンポーネントの機能として用意されています。
詳しくは公式のドキュメントが参考になります。
iOS のネイティブ UI にはそもそもチェックボックスがなく、なので indeterminate
ももちろんありません。(チェックボックスを再現するトグルボタン UI を作ろうと思えば作れます)
マークダウンでは
ちなみにマークダウンで以下のように書いたとしても、(マークダウンパーサー次第ですが) Gist などでは再現されません。
- [x] checked
- [ ] unchecked
- [-] indeterminate // Not Support
indeterminate を使うべきか
そもそも indeterminate なチェックボックスは必要なのでしょうか。入れ子のチェックボックス UI というのは果たして採用すべきなのでしょうか。
個人的には近年入れ子になったチェックボックスフォームはあまり見ないフォームで、かつ代替表現手段があると思うので、積極的に採用しなくてもよいのかなと考えています。
ケーススタディ: Gmail
Gmail が一番メジャーな採用ケースかと思います。PC 版ではメールの選択によってツールバーのチェックボックスが indeterminate になります。
しかし、スマートフォン Web 版やネイティブアプリ版では採用されておらず、数字をカウントしています。
このことから、
- 入れ子のチェックボックスで子が選択されていれば選択されている数を表示する
- チェックボックスを一括選択したいケースがある場合は、「すべて選択」ボタンにする
などの代替手段がありそうです。
スイッチという代替手段
2 値選択という意味では、スイッチという UI を採用するケースも増えているように思います。
スイッチは indeterminate
状態はなく、あくまでオンかオフかを表現する機能しか持ちません。
iOS や Android、Windows や macOS などの標準コンポーネントとして採用されています。
公式デザインガイドラインでも定義されており、参考になります。
直近の OS だと、Windows や macOS の設定画面で、チェックボックスとスイッチが混在しつつある感じがしますが、スイッチを採用するケースが優勢な印象を受けました。
注意: ブラウザは未対応
しかしウェブブラウザでは 2024 年 3 月現在、今の所標準で使用することができず、Safari Technology Preview でのみ確認することができます。
Safari Technology Preview では role
属性ではなく input type="checkbox"
を拡張して switch
属性を追加して表現しています。
<input type="checkbox" switch>
現在まだこの仕様は確定ではなく、Apple・Mozilla・Operaの開発者で構成されている whatwg では新たに <switch>
要素を作成することを言及しているケースもあります。
<switch>
ここの Pull Request などで議論されています。
しかし古いブラウザ環境との互換性を考えるとこちらに倒すのは少し難しいのかもしれません。
いずれにせよ role
属性は switch
となるようです。
悪魔生成: indeterminate がある switch
ちなみに web.dev の記事で、checkbox
の role
属性を見て CSS を当てて indeterminate
(未定義)を中間状態として見た目を悪魔生成する記事があります。
これは本来のスイッチの目的とはずれてしまっていますが、checkbox
を拡張した実装なのでこのような発明ができてしまっているようです。
iOS はチェックボックスを避けてきた
Apple の iOS 向け UI フレームワーク UIKit や SwiftUI ではチェックボックスは用意されておらず、macOS 限定となっています。代わりにスイッチを使用するのが一般的です。
iOS でチェックボックスが禁止されているわけではありません。チェックボックスという形ではなく、リストなどでたくさんの中からピックアップ・選択するときにチェックマークをつけるといった場面でチェックマークが登場したりはしています。
モバイル画面のサイズ制約上 indeterminate 的な機能を持つ UI はあまり見かけることはありません。トライステートの場合は SegmentedControl
を使うことも多いかと思います。
複雑なフォームを排するためだったり、スイッチに積極的に乗り換えさせるためにチェックボックスコンポーネントが避けてきていたようにも見えます。
感想
以上、ダラダラと書いてすみません。
採用ケースが減ってきているので見慣れない UI になっていって消えていくんだろうなと思いました。また、プライバシーセーフな昨今の規制により UI が整理されて闇が祓われている結果かも。
そういえばデジタル庁: Design System に定義されていなかったのは、あえて定義しなかったとかですかね。
実装はめんどくさいからしないけど、私は好きだったよ。