:focus-visible
と JavaScript
自己紹介
ますきー (@mascii_k)
(株)ビザスク
フロントエンドエンジニア
:focus-visible
とは?
- キー操作時のみスタイルを当てるための疑似クラス
- Chrome では 2020/10 から使えるようになった
:focus-visible
のデモ
JS でもキー操作中であるかわかるか?
document.querySelector()
で
:focus-visible
な要素を取得することができる
以下のようにしてキー操作中であるかがわかる:
const hasFocusVisible = () => {
try {
return !!document.querySelector(':focus-visible');
} catch {
// :focus-visible 非対応ブラウザ
return false;
}
};
:focus-visible
と WebComponents
Shadow DOM によって :focus-visible
な要素が隠蔽される
例: Wired ElementsReact Vue Angular Svelte
- Shadow DOM 内部の要素は
document.querySelector()
ではアクセスできない - つまり、
document.querySelector(':focus-visible')
が通用しない
WebComponents もキー操作中であるかわかるか?
Shadow Root のモードが closed
ではなく open
であれば、Shadow Root の
内部にアクセスすることで :focus-visible
な要素を取得することができる
以下のようにしてキー操作中であるかがわかる:
const hasFocusVisible = (): boolean => {
try {
// フォーカス中の要素またはコンポーネントを取得
let activeElement: Element | null = document.activeElement;
while (activeElement) {
// フォーカス中の要素が :focus-visible なものであるか判定
if (activeElement.matches(':focus-visible')) {
return true;
} else if (!activeElement.shadowRoot) {
return false;
}
activeElement = activeElement.shadowRoot.activeElement;
}
return false;
} catch {
return false;
}
};
document.activeElement
でフォーカス中の要素またはコンポーネントを取得できるElement#querySelector
は使うことがあったがElement#matches
は初めて使った- この実装をして
<iframe>
内部に:focus-visible
な要素があるケースに気付いた
まとめ
:focus-visible
を JS からも活用できた- Shadow DOM が絡むとフォーカス周りは難しい