
こんにちは。フロントエンドエンジニアの shoko です。
昨年から野球観戦にハマり、毎日の楽しみとなっています⚾️
今回は、キーボード操作時にどの要素がフォーカスされているかをユーザーに明確に伝えるために行ったフォーカスインジケータ改善の試行錯誤をご紹介します。
フォーカスが見えない問題
Tabキーなどを利用しキーボード操作でフォームやボタンを移動するとき、通常はフォーカスが当たった要素に枠線やハイライトが表示されます。しかし、「テックタッチ」の一部のコンポーネントでは、フォーカスが当たってもスタイルが変わらず、画面上でどの要素が選択されているのか視覚的に分からない状態でした。
このままだと、マウスを使わずキーボードだけで操作するユーザーは、フォーカスがどこにあるのか分からなくなり、操作に詰まってしまいます。

初期対応:CSSでフォーカスを見える化
まずは CSS の outline を使って、フォーカスされた要素に枠線を追加しました。
スタイルは既存のコンポーネントで使っていたものを流用しています。
button:focus-visible { outline: 2px solid #075BB7; }

これで基本的なフォーカス可視化は達成でき、キーボード操作でもフォーカス位置が分かるようになりました🎉
新たな課題:背景に埋もれるフォーカス
これで一安心…と思いきや、新たな問題が⚡️
フォーカスインジケータとして追加した青い枠線は、全ての場面で十分に目立つわけではないことが分かりました。
具体的には以下のようなケースで視認性が低下します。
- 例1:コンポーネントの背景色とフォーカスインジケータが同系色の場合

→ 青い枠線がボタンの色に埋もれてしまい、どこにフォーカスがあるのか分かりにくい
- 例2:コンポーネントの外側の背景色とフォーカスインジケータが同系色の場合(1つめの白背景ボタン)

→ フォーカスインジケータが背景と同系色になり、ほとんど見えなくなる
その結果、フォーカスが見えにくい場面があり、キーボード操作ユーザーにはどこを操作しているのか分かりづらい状態が残っていました。
最終改善:2色構成で視認性UP
WCAG解説書・達成方法集からヒントを得る
フォームやボタンなど、それぞれのコンポーネントに対して個別にフォーカススタイルを設定することもできます。
ただ、この方法だとコンポーネントが増えるたびに管理が煩雑になり、すべてのケースで一貫した視認性を保つのは難しくなります。
「あらゆるコンポーネントに適用できる、視認性に優れたフォーカスインジケータを設定する方法はないだろうか?」
そう考え、WebアクセシビリティのガイドラインであるWCAGの解説書「WCAG2.1 解説書 - 達成基準 2.4.7: フォーカスの可視化を理解する」を改めて見直しました。
この解説書には「十分な達成方法」として6つの実装例が掲載されています。
その中で、まさに自分が直面していた課題を解決できそうな方法を発見しました👀
C40: すべてのコンポーネントで十分なコントラスト比を確保するために2色のフォーカスインジケータを作成する
この方法では、1色のフォーカスインジケータに加えて、外側にもう1色(白など)を追加します。これにより、背景色の影響を受けにくくなります。
この例を参考に、実際に実装してみました。
2色構成のフォーカスインジケータ
outline と box-shadow の組み合わせで、背景色に左右されず視認性の高いスタイルを実現。
button:focus-visible { outline: 2px solid #075BB7; /* 内側の青い枠線 */ box-shadow: 0 0 0 5px #FFFFFF; /* 外側に白い枠線 */ }
2色構成により、背景色とフォーカスインジケータが同系色になるケース(例2)は解消されました🙌
しかし、コンポーネント自体の背景色と枠線が似ている場合(例1)では、依然としてフォーカスインジケータが見えづらい状態が残ります。
この課題を解決するため、outline-offset でフォーカスインジケータを要素から少し外側にずらしました。
button:focus-visible { outline: 2px solid #075BB7; /* 内側の青い枠線 */ outline-offset: 1px; /* 内側の枠線を1px外側にずらす */ box-shadow: 0 0 0 5px #FFFFFF; /* 外側に白い枠線 */ }
outline-offset でフォーカス枠線を外側にずらすことで、青い枠線と白い影(box-shadow)が分離し、色が近いコンポーネントでも境界が見えるようになりました。
最終改善前後のイメージがこちらです👇

背景やコンポーネントの色に左右されないフォーカスインジケータの完成です🎉
デフォルトのフォーカスインジケータを使わなかった理由
ちなみに、実装検討の段階ではブラウザのデフォルトフォーカスインジケータをそのまま使うことも考えました。
しかし、例えば Chrome ではフォーカス枠が青色で、青いボタンと組み合わせるとやはり見づらく、視認性が十分に確保できなかったため採用は見送りました。

なお、デフォルトのフォーカス枠の色は OSやブラウザ、テーマ設定によって変わるため、これはあくまで私の環境(macOS / Chrome / Light モード)での例です。
おわりに
今回の改善では、WCAG達成方法集の実装例が大きなヒントになりました。
また、例1のように背景色と枠線が似ているケースでは、outline-offset を2pxに調整することでさらに視認性が上がるのではと考えており、今後も改善を重ねていきたいと思います。