フォーカスアピアランスの達成基準についての考察
これはアクセシビリティ Advent Calendar 2021の 18 日目の記事です。
現在草案段階である WCAG 2.2 には「フォーカスアピアランス[1]」という達成基準が追加されています。基準は「2.4.11 Focus Appearance (Minimum)」と「2.4.12 Focus Appearance (Enhanced)」とふたつあり、適合レベルはそれぞれが AA と AAA となっています。
今回、AA の方である Understanding Success Criterion 2.4.11: Focus Appearance (Minimum) を読み、ざっくりとこの達成基準がどういった目的で作られたのか、また現段階でどういった実装が適合もしくは不適合になるのかを考えてみたいと思います。
フォーカスインジケータに関わる基準
WCAG 2.2 の草案が最初に公開された時点では、この 2.4.11 は「Focus Visible (Enhanced)」というタイトルがつけられていました[2]。つまり「2.4.7 フォーカスの可視化」の強化版だったわけですが、さらに 2.4.12 が更に追加され、2.4.7 はレベルが AA から A にとなったため、フォーカスインジケータに関する達成基準が 3 段階のレベルで定義されることになります。
達成基準 | 適合レベル | 追加されたバージョン |
---|---|---|
2.4.7 フォーカスの可視化 | A(AA から変更) | 2.0 |
2.4.11 Focus Appearance (Minimum) | AA | 2.2 |
2.4.12 Focus Appearance (Enhanced) | AAA | 2.2 |
2.4.7 では基本的に「フォーカスインジケータが見えること」で適合となります。失敗例もインジケータを視覚的に完全に消していることのみとなっており、「十分な達成方法」や「さらに対応が望まれる達成方法」として『目立つ』という言葉をつかっているものの、その具体的な閾値は示されていませんでした。それが今回の 2.7.11 と 2.7.12 では、具体的な数値や計算方法が『面積』や『カラーコントラスト』で規定されることになります。
面積とコントラスト
まずは原文を読み解いてみます。
Success Criterion 2.4.11 Focus Appearance (Minimum) (Level AA): When user interface components receive keyboard focus, an area of the focus indicator meets the following:
- Minimum area: The area is either:
- at least as large as the area of a 1 CSS pixel thick perimeter of the unfocused component, or
- at least as large as the area of a 4 CSS pixel thick line along the shortest side of a minimum bounding box of the unfocused component, and no part of the area is thinner than 2 CSS pixels.
- Contrast: The area has a contrast ratio of at least 3:1 between the colors when the component is focused and it is not focused.
- Adjacent contrast: Where the area is adjacent to the component, it has a contrast ratio of at least 3:1 against the component or a thickness of at least 2 CSS pixels.
「最低限の面積」「コントラスト」「隣接するコントラスト」の 3 つ条件が規定されています。
面積とは、インジケータのピクセル単位の面積です。インジケータを表すドットが何個あるのか、ということですね。興味深いのはコンポーネントの面積に対して何割という計算などではなく、「周囲(perimeter)」や「バウンディングボックス」が基準になっている点です。あくまで基本はアウトラインやボーダーを拡張するような計算です。計算についての考察は後述します。
コントラストは、フォーカスされているときとされていないときの、インジケータの部分の表示前後の色のコントラスト比を表します。動的な色の変化量を見ているということですね。この達成基準の肝といえます。
隣接するコントラストは、少し面白い規定です。隣接しているコンポーネントとインジケータのコントラスト比を高くすることは「1.4.11 非テキストのコントラスト」という規定の存在からもわかりやすいのですが、太さが 2px 以上であればコントラストは問わない点が興味深いです。つまり太さがあれば隣接した色は同じでも構わないということですね。「フォーカスインジケータ自体を知覚できるか」というよりも「フォーカスされていないコンポーネントと、フォーカスされているコンポーネントに視覚的な差をつける」ことが本質であると示唆しています[3]。
面積の計算
次のどちらかを満たす必要があります。(意訳です。)
- フォーカスされていない状態のコンポーネントの 1px の太さの周囲の面積以上
- フォーカスされていない状態のコンポーネントの最短の辺 ×4px の面積以上で、且つインジケータの厚さ 2px 以上
1px の太さの周囲の面積以上
矩形の場合は次のような式になります。
3×3 であれば「3 + 3 + 3 + 3 - 4」で 8 平方 px、20×10 なら「20 + 20 + 10 + 10 - 4」で 56 平方 px 必要ということですね。
要するに、1px のボーダーを作ったときのボーダーのドットの数を単純に数えればいいわけです[4]。
円の場合は円周を計算すればよいのですが、楕円になったりするととたんに複雑な計算式になりますし、角丸は半径と矩形の計算から導き出せますがややこしい計算になります。少なくとも矩形の周囲で計算しておけば理論上は円や角丸よりも面積は大きくなるはずなので、大まかな計算でよい場合はバウンディングボックスを周囲として計算すればいいと思います。
元の解説にもある星型などの複雑な形は、微積分を持ち出してまで計算はしたくないので…なにか検討する必要があるでしょうね。少なくとも形状より外側に大きな相似のアウトラインを作れば、それは面積が規定以上になるので無難に対応するならそれが一番簡単な解決方法です。ただ、複雑な形状のフォーカス可能要素はそれ自体がかなり特殊なものになると思うので、きちんと計算してトコトンデザインするのもいいのかもしれません。
コンポーネントの形状と同じアウトラインを作る場合は、
- 外側に作る場合の太さは 1px 以上あれば OK
- 内側に作る場合の太さは 2px 以上は必ず必要(1px では足りない)
ということがわかりますね[5]。
最短の辺 ×4px の面積以上で、且つインジケータの厚さ 2px 以上
最短の辺とは、幅と高さの短いほうを指します。20×10 の矩形であれば、10px のほうが最短の辺ですね。そして、それに 4px をかけた面積が最低限の面積となり、20×10 の矩形では「10 × 4 = 40」で 40 平方 px が、50×200 でも 50×300 でも最短の辺は 50 なので「50 × 4 = 200」で 200 平方 px が必要な面積になります。
そして、更にその必要な面積を満たした上で、インジケータ厚さがそれぞれ 2px 以上でないといけないというわけです。つまり 「面積」だけの要件ではない ことに注意が必要です。また、「厚さ」としているのは、インジケータが「面」になるのか「線」になるのかわからないので「幅や高さ」ではなく「厚さ」としているのでしょう。
周囲面積計算と最短辺計算どちらが緩いのか
今までの計算で、20×10の矩形の場合は、
- 周囲面積計算: 20 + 20 + 10 + 10 - 4 = 56
- 最短辺計算: 10 × 4 = 40
であったので、最短辺計算のほうが基準が緩くなりましたが、他の場合どうでしょう。
仮に、幅10px、高さ10pxで正方形にしてみます。
- 周囲面積計算: 10 + 10 + 10 + 10 - 4 = 36
- 最短辺計算: 10 × 4 = 40
と、周囲面積計算の方が緩くなりました。
おそらく、縦横の比の差がゼロに近づくにつれてどこかで逆転するのでしょうけど[6]、とりあえず 一方の計算だけで済ますということはできない ということがわかります。
絶対ピクセル値の要件とオブジェクトの拡縮
周囲計算や隣接するコントラストで登場した「2px」という絶対値ですが、なかなかうまい制約を作っている反面、拡縮可能なコンポーネントや画面ではきちんと理解した上で実装に取り掛からないといけないと考えます。
というのも、コンポーネントを縮小するとフォーカスインジケータごと縮小されて2pxの厚さが2px未満になった場合に、それがおそらく不適合となるからです。原文には言及されていませんが、実際問題スクリーン上で2px未満になることは問題となるでしょう。
この問題は、グラフィックツールのウェブアプリケーションや、3Dオブジェクトを扱うVR技術などで発生しうると思います。グラフィックツールでは、視覚的にバウンディングボックスを表示する場合、対象のオブジェクトが拡大状態であろうが縮小状態であろうが、影響を受けないレイヤー上に存在していてインジケータの厚さを保っています。バウンディングボックスと同様にフォーカスのインジケータでもそういった実装が必要になるでしょう。3DやVRの実装は詳しくありませんが、オブジェクトととの距離やカメラの位置でスクリーン上のオブジェクトの大きさは変わります。オブジェクトと同じ概念のレイヤーにあるとフォーカスインジケータも影響をそれに受けてしまうので、グラフィックツールと同じく別のレイヤーを作る必要があるでしょう。CSSで3Dを表現している場合には、フォーカスインジケータを発生させる要素と、transform
を適用する要素の関係には十分に気をつけなければなりません。
フォーカス以外の表現との混乱
思っていたよりも表現の自由度が下がることはなく柔軟な基準になっているなという印象を受けますが、自由度が高いぶんその表現方法によってはほかの問題を引き起こさないかどうかは十分に注意を払わなければなりません。
インターフェイスの状態(ステート)は当然ながらフォーカスだけではありません。
- マウスポインタが乗っている状態(
:hover
) - マウスポインタでクリックしている状態(
:active
) - 選択されている状態(
selcted
aria-selected
) - チェックされている状態(
checked
aria-checked
) - 押されている状態(
aria-pressed
) - 入力エラーがある状態(
aria-invalid
)
これら[7]の状態とフォーカス状態が共存する場合も当然あります。それらを示す表現が「いったいどの状態を示しているのか」ユーザーが判断できるようにする必要があります。「フォーカス状態だと思ったけど選択状態だった」「フォーカス状態だと思ったら気づいたらマウスポインタが重なっているだけだった」といったように、混乱を招かないような表現が望ましいです。インターフェイスの役割や、使用頻度、文脈や短い操作による学習で明らかになるかどうかなど、評価する基準や判断材料は変わるとは思いますが、少なくともOSやブラウザにない表現を使うのであれば、このあたりは十分に検討と検証を重ねる必要があるでしょう。
勉強会やりましょう
先に書いたとおり、この基準は まだ草案段階です 。また、当然すべてが僕の解釈によるものなのですべてが憶測です。なのでこの解釈は妥当なのかどうか、確認したいと思っているので、この記事に対してコメントやTwitterでのツッコミ大歓迎ですので、一緒に読み解いていけたらと思っています。
そして、勧告された際には改めてWCAG 2.2勉強会をやりましょう。
-
日本語による公式的な翻訳はまだのため著者訳。原文名: Focus Appearance ↩︎
-
まあ、でも言うても 2px の差って小さすぎやしないか?というのは、それはそう思うところです。非テキストに対してのそのあたりがテキストと比べて緩いのは今に始まったことじゃないのですが…。 ↩︎
-
ただし、解像度は 1 倍で、
box-sizing: border-box
だったとする。原文がボーダーではなく「周囲(perimeter)」という言葉を使っているのは、ボーダーだとbox-sizing
に影響を受ける点で混乱しないためなのではと思ったり思わなかったり。 ↩︎ -
内側の場合、外側から内側への距離(
outline-offset
)がどのくらい離れると 2px でも足りなくなるかどうか、つまり「オフセット距離と必要な太さ」の関係にはおそらく規則性があるので、なにか方程式や定理が既にありそうな気もします。数学詳しい方、もしなにかご存知でしたら教えて下さい。 ↩︎ -
これも数学に詳しい方がいらっしゃったら方程式ください。 ↩︎
-
すべてを挙げたわけではありません ↩︎
Discussion