見た目重視でoutlineを消したいにしても、せめてこうしませんか?


これは何

  • (おそらく)見た目を重視してoutline: 0を指定するのはやめて、こうしませんか?という提案の記事
    • UAで付与されるoutlineがイケてなく感じる気持ちは分かります
    • しかし安直にoutlineを消すとアクセシビリティが下がってしまうので、代替案を提示してみます

そもそもなぜoutlineを消すのが良くないのか

outlineは「今自分が何の要素にフォーカスを当てているか」を示してくれます。

そのoutlineを消してしまうと、ページの操作をキーボードで行っている人が非常に困ります。
マウスを使わず(あるいは使えず)操作をしている人にとっては、outlineが表示されていないと実質操作不可能なのです。

せめてキーボードユーザーにだけはoutlineを出しておく

とは言え、マウスを使っているユーザーにとってはフォーカス位置が分かってもそこまでメリットがないと思います。
そこで提案するのが以下のライブラリを使用することです。

こちらを使うと、インプット方法がmouse, keyboard, touchのうちどれなのかを判定できるようになります。

「マウスを使っているユーザーのoutlineは消す」「キーボードを使っているユーザーのoutlineは表示する」と出し分けられるようになり、およその問題は解決すると思われます。

WCAGの達成基準2.4.7に記載されているメリットによれば「注意力欠如、短期記憶の制約、又は遂行機能における制限のある利用者が、フォーカスがどこにあるのかを見つけることができるようになる。」ともあるので、これに該当する人たちへのフォローはできませんが……。)

具体的な導入方法

※ ここからはwhat-input公式のドキュメントに書いてある以上のことはほとんど記載していません。

まずはnpmかyarn、好きな方を選んでインストールしてください。

インストール
npm install what-input

# or

yarn add what-input

scriptタグで直接読み込むか

<script src="path/to/what-input.js"></script>

以下のいずれかのimportをします

import 'what-input'

// or

import whatInput from 'what-input'

// or

require('what-input')

// or

var whatInput = require('what-input')

// or

requirejs.config({
  paths: {
    whatInput: 'path/to/what-input',
  },
})

require(['whatInput'], function () {})

インポートできたら、以下のようにCSSに記載をすれば「マウスを使用しているユーザーにだけoutlineを非表示」を実現できます。

グローバルなCSS
[data-whatinput='mouse'] *:focus {
  outline: none;
}

なお、公式では[data-whatinput='mouse'] *:focusではなく[data-whatintent='mouse'] *:focusで記載されていますが、個人的にはdata-whatinputの方が良いと思いました。

少し分かりづらいので以下のgifをご覧ください。

data-whatintent data-whatinput

どちらも操作している内容は

  • tabキーでフォーカスをあてる
  • マウスを動かす
  • 再びtabキーを押す

と変わりません。

data-whatintentの方は、ちょっとでもマウスを動かすと、例えクリックをしていなくてもフォーカスインジケータが消えてしまいます。
また、マウスを触った直後にtabキーを押しても、フォーカスは移動するのにインジケータが表示されません。

キーボード操作をしつつも一応マウスをつないでいる……といった人がいた場合、うっかりマウスを触ってしまったらフォーカスインジケータが消えてしまうのでdata-whatinputの指定の方が良いと思った次第です。