フォーカスインジケーターの実装ってどんなのが良いのだろうと悩み、眠れない夜を過ごした。

に公開
1

一言で言うと

フォーカスインジケーターは

  1. コントラストを最優先
  2. 太さは2px以上がベスト
  3. box-shadow・outline-offsetなどを使い二重になるようにする
  4. 状態ごとの差別化
  5. :focus-visibleを使用する

ある日事件は起きた

弊サービス、ランサーズのサイトを見ていて気づいてしまった。
ボタンのフォーカスが見づらすぎる。。

フォーカス前 フォーカス後

いやサイゼの間違い探しかよw
アウトラインの色とボタンの色がほとんど同じになっているみたい。
詳しく調べてみると、ボタンなどに使われている会社のメインカラー#0268ccと、Chromeのフォーカス色rgb(0, 95, 204)が極めて似ているからのよう。

世のデザインはどなっているのか

ユーザーエージェント(Chrome)

そうそうこれこれ。シンプルで拡張性抜群。基本的にはこれで問題ない。

:focus-visible {
    outline: -webkit-focus-ring-color auto 1px;
}
a:-webkit-any-link:focus-visible {
    outline-offset: 1px;
}

(outline-offsetはbuttonにはないのか。)

Material Designのサイト

MaterialDesign

.ctas[_ngcontent-via-c21] a[_ngcontent-via-c21]:focus-visible, .ctas[_ngcontent-via-c21] a[_ngcontent-via-c21]:hover:focus-visible {
    margin: -4px auto 12px;
    border: 2px solid #1c1b1d;
    border-radius: 18px;
    outline: 0;
    box-shadow: inset 0 0 0 2px #fff;
}
a:focus {
    margin: -1px;
    border: 1px solid var(--mio-theme-color-primary);
    outline: 0;
    box-shadow: inset 0 0 0 1px var(--mio-theme-color-surface-0);
}
フォーカス前 フォーカス後

外側2pxの黒い枠線と内側2pxの白いボックスシャドウ、さらに丸みを帯びた角のフォーカスインジケーター。
角丸のためにoutlineを使わずにborder/box-shadow/marginで調整していて、マテリアルデザインらしい見た目になっている。

デジタル庁

デジタル庁

.anchor-card:focus-visible, a.card:focus-visible {
    outline-color: #000;
    outline-offset: .125rem;
    outline-style: solid;
    outline-width: 4px;
    --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
    --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0.125rem + var(--tw-ring-offset-width)) var(--tw-ring-color);
    box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
    --tw-ring-opacity: 1;
    --tw-ring-color: rgb(255 212 61 / var(--tw-ring-opacity));
}
フォーカス前 フォーカス後

テキストのa要素のフォーカス

黄色!!圧倒的わかりやすさ!!
外側は黒で4pxのoutline、内側は0.125remオフセット、黄色のbox-shadowで表現。
Tailwind CSSのカスタムプロパティでリング色・透明度やサイズが細かく調整されている

Spindle

Spindleのデザインシステムページ

.spui-LinkButton:focus:not(:focus-visible) {
    outline: none;
}
.spui-LinkButton:focus {
    outline: 2px solid var(--LinkButton-onFocus-outlineColor);
    outline-offset: 1px;
}

フォーカス前 フォーカス後

LinkButtonコンポーネント

ほとんどユーザーエージェントのデフォルトに近いデザイン。
古より伝わる:focus:not(:focus-visible)を使うことでfocus-visibleに対応していない古いブラウザにも対応している。

フォーカスインジケーター改善のポイント

  1. コントラストを最優先
    ボタン本体や背景の色と違う、どんな時でも十分に目立つ色を選ぶのが良い。ブランドカラーが目立たない場合は補助色やアクセント色にするのが良さそう。3:1のコントラスト比があるようにする。

  2. 太さは2px以上がベスト
    太さが1pxのoutlineだけだとかなり見づらい。単に幅を大きくしたり二重にするなどして2px以上、または一目で区別できるサイズ感にしたい。

  3. box-shadow・outline-offsetなどを使い二重になるようにする
    outlineだけだと境界が分かりづらくなることがある。
    可能ならbox-shadowやoutline-offsetなどを使い、外側・内側など多重でわかりやすくすると良い。

  4. 状態ごとの差別化
    hoverやactiveと被らないように、インジケーターのスタイルや色を切り替える。

  5. :focus-visibleを使用する
    今から新しく作るのであれば、focus-visibleを使ってtabキー操作の時のみのインジケーターを設定したい。

最後に

今回は主にa要素とbutton要素を確認したが、インタラクティブ要素はinput、select、details、dialogなど他にもあるので、実装するときはそれらで使っても問題ないかを確認しておきたいですね。PCのシステム設定(例えばハイコントラストモード)などでも見た目が変わるので意外と奥が深そう。今後も気づいた点や追加の知見があれば、この記事に追記していく予定です。

ということで、弊サービスでも無事フォーカスインジケーターが見やすくなりました。

フォーカスなし フォーカスあり

参考

フォーカスの外観 (レベル AAA)
書籍:Webアプリケーションアクセシビリティ P.84
box-shadow で実装されたフォーカスリングはハイコントラストモードで表示されない

ランサーズ株式会社

Discussion

nnnwannnwa

地味だけど、と言っては失礼ですが、地味に大事な要素ですよね、、、
なかなか作ってるときは拘りきれずに作っちゃいますが、ユーザーがUI見るのは一瞬で、離脱も一瞬ですもんね。。。参考になりました。