jsx-a11y 用 ESLint プラグインを導入する
当方 Create-React-App (CRA) のプロジェクトにおけるアクセシビリティを考慮するため、jsx-a11y 用 ESLint プラグイン eslint-plugin-jsx-a11y をインストールすることにしました。
# npm
npm i -D eslint-plugin-jsx-a11y
# yarn
yarn add -D eslint-plugin-jsx-a11y
実際に導入する
下記のように .eslintrc.js
の extends
と plugins
に設定します。
module.exports = {
extends: ['plugin:jsx-a11y/recommended'],
plugins: ['jsx-a11y'],
}
ルールセット
ルールセットは 2 種類あります。
jsx-a11y/recommended
jsx-a11y/strict
基本的にどちらのルールセットを使っても構わない。
対応ルール全てエラーと認識してくれる一方、一部ルールではエラーと見做さないケースも設定できたりなど、弾力的に運用できます。
まず、マウスやキーイベントのリスナーなどに role を付けます。
該当のルールは下記の通りとなります。
次に、非対話型の HTML 要素や WAI-ARIA ロールはマウスやキーイベントのハンドラーをサポートしないので role を付ける。
:::message is-primary
非対話型の HTML 要素
<main>
、 <area>
、 <h1>
、 <h2>
、 <h3>
、 <h4>
、 <h5>
、 <h6>
、 <p>
、 <img>
、 <li>
、 <ul>
、 <ol>
非対話型の WAI-ARIA ロール
<article>
、 <banner>
、 <complementary>
、 <img>
、 <listitem>
、 <main>
、 <region>
、 <tooltip>
:::
該当のルールは下記の通りになります。
最後に th 要素のみ scope を許容します。
該当のルールは scope です。
あらゆる warning を解決する
eslint-plugin-jsx-a11y を読み込んで eslint --fix
してみます。
# eslint
npx eslint . --ext ts,tsx --fix
修正すべき warning に遭遇しなければ、導入完了とみて問題無いだろう。しかし、いくつかの warning に遭遇することがあります。
具体的には div
などに代表される静的な HTML 要素で onClick
イベントを使ってしまっているケースなどが挙げられます。
jsx-a11y/click-events-have-key-events
onClick
イベントを使う場合、マウスを使用できないユーザのために onKeyUp
/ onKeyDown
/ onKeyPress
を考慮する必要があります。
もちろん 1 つも無ければ、アクセシビリティ的なアウトになります。
const Component = () => <div onClick={() => {}}>{/* 何らかのコンテンツ */}</div>
なお、広くボタン用途に使われる button
要素で onClick
イベントを使用した方が良いと考えています。
この button
要素では既に onKeyUp
/ onKeyDown
/ onKeyPress
が考慮されています。
const Component = () => <button onClick={() => {}}>{/* 何らかのコンテンツ */}</button>
jsx-a11y/no-static-element-interactions
div
など静的な HTML 要素でマウスやキーイベントを設定する場合に、要素の role 属性を設定する必要があります。
const Component = () => (
<div onClick={() => {}} role="button">
{/* 何らかのコンテンツ */}
</div>
)
onClick
イベントと合わせて role 属性を設定しても特に問題はありません。
ただし、広くボタン用途で使われる button
要素に変更する選択肢を取った方が良いと考えています。
const Component = () => <button onClick={() => {}}>{/* 何らかのコンテンツ */}</button>
最後に
とあるプロジェクトで ESLint プラグインを設定した当初 70 近い warning を観測しました。
✘ 68 problems (68 errors, 0 warnings)
Errors:
29 jsx-a11y/click-events-have-key-events
28 jsx-a11y/no-static-element-interactions
5 jsx-a11y/aria-role
2 jsx-a11y/media-has-caption
2 jsx-a11y/anchor-is-valid
1 jsx-a11y/no-autofocus
1 jsx-a11y/no-noninteractive-element-interactions
しかし、そのどれもが同じようなエラーのため、そこまで怖がる必要はありません。
アクセシビリティの ESLint に伴う --fix
をビルド時に強制したことで、最低限の品質を担保させるようにしました。
その他
eslint-plugin-jsx-a11y でサポートされているルール一覧になります。
視覚によるチェックでは確認しきれない部分を補うため、コードベースでコンポーネントごとに自動チェックします。
<!--
eslint-plugin-vuejs-accessibility
eslint-plugin-vuejs-accessibility でサポートされているルール一覧です。
視覚によるチェックでは確認しきれない部分を補うため、コードベースでコンポーネントごとに自動チェックする。
Rule | Recommended |
---|---|
accessible-emoji | error |
alt-text | error |
anchor-has-content | error |
aria-props | error |
aria-role | error |
aria-unsupported-elements | error |
click-events-have-key-events | error |
form-control-has-label | error |
heading-has-content | error |
iframe-has-title | error |
interactive-supports-focus | error |
label-has-for | error |
media-has-caption | error |
mouse-events-have-key-events | error |
no-access-key | error |
no-autofocus | error |
no-distracting-elements | error |
no-onchange | error |
no-redundant-roles | error |
role-has-required-aria-props | error |
tabindex-no-positive | error |
--> |