
ボタンが押し込まれた状態を表す Press Button の提案
UI デザインにおいてボタンが「押し込まれた」状態を表現することはしばしばあります。しかし、ネイティブの HTML 要素では表現できず `aria-pressed` 属性を使用する必要がありました。Press Button Proposal では `type="press"` 属性を追加することでボタンが押し込まれた状態を表現することが提案されています。
UI デザインにおいてボタンが「押し込まれた」状態を表現することはしばしばあります。代表的な例としてミュートボタンがあります。ミュートボタンは音声の入力をミュートにするためのボタンで、押し込まれた状態であればミュートになり、押し込まれていない状態であればミュートが解除されていることを表します。
今まではボタンが押し込まれた状態を表現するためにいくつかの方法がありました。
- aria-pressed 属性を使用する
- ボタンの状態に応じてラベルを変更する(例: ミュート、ミュート解除)
aria-pressed
属性を使用する方法では aria-pressed=true
であればボタンが押し込まれている状態を表します。スクリーンリーダーには「選択中、ミュート、切り替えボタン」のように読み上げられます。aria-pressed
属性を使用している場合には、状態が変更されたとしてもボタンの状態を表すラベルは変更してはいけません。
aria-pressed
属性はボタンをクリックするたびに更新されることが期待されます。また値を更新する場合には JavaScript を使用する必要があります。
<button aria-pressed="true">ミュート</button>
<script>
const button = document.querySelector("button");
button.addEventListener("click", () => {
button.setAttribute(
"aria-pressed",
button.getAttribute("aria-pressed") === "true" ? "false" : "true",
);
});
</script>
しかしボタンが押し込まれた状態を表すために aria-*
属性を使用しなければいけないという状況はあまり好ましくありません。なぜなら、「必要なセマンティクスと動作がすでに組み込まれたネイティブの HTML 要素や属性を使用できる場合は、ネイティブのものを使用する」という WAI-ARIA の原則に反しているからです。これはつまり <button>
要素が使える状況であるならば、<div role="button">
を使用するべきではないということです。
このようにネイティブなものが存在しないため aria-*
や role
属性を使わざるをえない例として role="search"
がありました。この問題はネイティブの <search>
要素が登場したことにより解決されました。
<search>
要素と同じ役割が期待されているのが Press Button の提案です。これは Open UI Community によって提案されており、aria-*
属性や JavaScript を使用せずにボタンが押し込まれた状態を表現することが目的です。
Press Button の概要
Press Button Proposal では以下の事項が提案されています。
<button>
要素のtype
属性の値にpress
を追加する- css 擬似クラス
:pressed
を追加する - 新しい属性
defaultpressed
を追加する - IDL プロパティに
pressed
を追加する。このプロパティはtrue
,false
,mixed
のいずれかの値を持つ - UA スタイルシートに
button:pressed
のスタイルルールを追加する
type="press"
属性を追加した場合、暗黙的に pressed
状態を持つことになります。初期状態は false
です。defaultpressed
属性を使用することで初期状態を true
もしくは mixed
に設定できます。
type="press"
属性を持つボタンはクリックされるたびに pressed
状態がトグルされます。pressed
状態 true
の場合は :pressed
擬似クラスが適用されます。開発者は :pressed
擬似クラスを使用して視覚的にボタンが押し込まれた状態を表現できます。pressed
状態が mixed
の場合には :indeterminate
擬似クラスが適用されます。
代替案
Press Button Proposal の代替案として過去に以下のような提案がありました。
<input type="checkbox">
要素を使用するtype="press"
ではなくpress
属性を使用する
<input type="checkbox">
要素を使用する
トグル状態を表現する方法として <input type="checkbox">
要素は一般的な方法として知られています。また似たようにトグル状態を表す
switch もチェックボックスの新しい属性として Safari に実装されました。以下の 2 点の理由から Press Button Proposal では <input type="checkbox">
要素を使用しないことが決定されました。
- チェックボックスやスイッチはフォーム内で使われることが一般的であるが、Press Button はそうではない
- Press Button もまたボタンであるので、ボタン要素を使用することが理にかなっている
press
属性を使用する
boolean 値を持つ press
を追加するのではなく、type="press"
を使うように決定されたのはなぜでしょうか?type
属性に新しい値を追加する方法は 1 つ欠点があります。それは誤った値を指定した場合 type="submit"
にフォールバックすることです。これは type="press"
をサポートしていない古いブラウザで問題となる可能性があります。
しかし、「<input type="checkbox">
要素を使用する」でも述べられているように、Press Button はフォーム内で使われることはあまりないと考えられています。フォームの送信の問題を除けば、人間工学的に type="press"
が適切であると考えられています。
例えばデフォルトで押された状態のボタンの書き方を比較すると、type="press"
のほうが boolean を持つ状態が減っているため、よりシンプルに感じられます。
<button type="press" defaultpressed="true"></button>
<button type="button" press defaultpressed></button>
また、type="press"
の場合 Press Button を誤って submit
や reset
として扱ってしまうミスを防ぐことができます。
より優れた代替案として enum の値を持つ press
属性を使用することも考えられます。これは defaultpress
属性と IDL プロパティを持つ必要性がなくなるので有力です。
<button type="button" press="true"></button>
これは type="press"
と比べてより明確になる可能性はありますが、状態の反映に依存するため好ましくないと考えられています。また、既存の他の要素とも一致していません。
まとめ
- UI デザインにおいてボタンが押し込まれた状態を表現することは一般的であるが、ネイティブの HTML 要素では表現できず
aria-presed
属性を使用する必要があった - Press Button Proposal では
type="press"
属性を追加することでボタンが押し込まれた状態を表現することができる defaultpressed
属性を使用することで初期状態を設定できる:pressed
擬似クラスを使用してボタンが押し込まれた状態を視覚的に表現できる