a11y.cssによるマークアップの品質チェック
エグゼクティブ・フェロー 木達この記事はミツエーリンクスアドベントカレンダー2019 - Qiitaの25日目の記事です。
「アリックス」と発音するそうですが、a11y.cssという名前の、一種の品質チェックツールについてご紹介します。
a11y.cssの概要
accessibilityの省略表記として「a11y」という表記が英語圏を中心に根づいている昨今、あたかもアクセシビリティ品質に特化したチェックツールかと思われるかもしれませんが、そういうわけではありません。アクセシビリティに関わるものを含め、マークアップに潜むリスクや間違いを指摘するものです。
Firefox用のアドオンやChrome用の拡張のほか、後述するレベルと言語(英語のほかロシア語、中国語、アラビア語、ポルトガル語、ギリシャ語が選択可能)を組み合わせて生成するブックマークレットから使用することができます。
指摘の対象はエラー(Errors)、警告(Warnings)、時代遅れ(Obsoletes)、アドバイス(Advices)という4つのレベルに分類されています。数がやや多いのですが、本稿執筆時点の最新版において、どんなマークアップを指摘するか列挙します(リンク先はそれぞれ、英語で書かれた公式サイト上の解説です):
エラー
- accesskey属性
 - img/object/embed/svg/canvas以外の要素に指定したwidth/height属性
 - disabled/readonly属性を指していないにも関わらず、無効化を意図したと思しきbutton要素
 - aria-label/aria-labelledby/title属性を指定していないにも関わらず、内容が空のbutton要素
 - aria-label/aria-labelledby/title属性値が空のbutton要素
 - for属性値が空もしくは空白文字のlabel要素
 - href属性値が空もしくは空白文字のa要素
 - aria-label/aria-labelledby/title属性を指定していない、もしくは指定していても属性値が空で、要素内容が空のa要素
 - charset属性値にutf-8/UTF-8を指定していないmeta要素
 - type属性値がradio/checkboxで、name属性を指定していないinput要素
 - 値にrtl/ltr/auto以外を指定したdir属性
 - onmouseover属性などのイベントハンドラ
 - charset属性を指定したmeta要素が内容の最初にないhead要素
 - 妥当ではないid/class属性値
 - インタラクティブな要素の妥当ではない入れ子
 - action属性を指定していないか、action属性値が空もしくは空白文字のform要素
 - alt属性が指定していないか、alt属性値が空白文字のimg/area/type属性値にimageを指定したinput要素
 - role属性値がimgで、かつaria-label/aria-labelledby属性を指定していない要素
 - ラベルを指定していないinput/textarea/select要素
 - lang属性で言語を指定していないhtml要素
 - 要素内容が空のtitle要素
 - src/srcset属性値が妥当ではない画像
 - title属性を指定していない、もしくは指定していても属性値が空もしくは空白文字のiframe要素
 - type属性を指定していない、もしくは指定していても属性値が空もしくは空白文字のinput要素
 - type属性値がreset/submit/buttonでラベルを指定していないinput要素
 - type/form/formaction/formtarget属性を指定していないbutton要素
 - type属性値がreset/buttonでformmethod/formaction/formtarget/formenctype/formnovalidate属性を指定していないbutton要素
 - label属性を指定していないoptgroup要素
 - fieldset要素内容にない、type属性値radioを指定したinput要素
 - role属性値checkboxを指定しているにも関わらず、aria-checked属性を指定していない要素
 - role属性値comboboxを指定しているにも関わらず、aria-expanded属性を指定していない要素
 - role属性値scrollbarを指定しているにも関わらず、aria-controls/aria-valuemin/aria-valuemax/aria-valuenow/aria-orientation属性を指定していない要素
 - role属性値sliderを指定しているにも関わらず、aria-valuemin/aria-valuemax/aria-valuenow属性を指定していない要素
 - role属性値spinbuttonを指定しているにも関わらず、aria-valuemin/aria-valuemax/aria-valuenow属性を指定していない要素
 - tabindex属性値に0より大きな値を指定している要素
 - レイアウト目的と思しき(role属性値presentationを指定した)table要素に含まれる、th/thead/tfoot/caption/colgroup要素またはaxis/scope/headers属性を指定した要素
 - アクセシブルではないビューポート指定をしたmeta要素
 
警告
- autoplay属性
 - controls属性を指定していないvideo/audio要素
 - 装飾目的であるにも関わらずtitle/aria-label/aria-labelledby/aria-describedby属性を指定した画像
 - details要素内容の最初にないsummary要素
 - 空のalt属性を指定した要素
 - body要素にあって表示されているにも関わらず内容が空の要素
 - title属性を指定していないか、title属性値が空または空白文字のabbr要素
 - fieldset要素内容の最初にないlegend要素
 - role属性値groupを指定していないfigure要素
 - alt属性値にファイル名を指定していると思しき要素
 - ボタンとしての動作を指定していないにも関わらず、href属性値にjavascriptスキームを含むa要素
 - 妥当ではない並びのdt/dd要素
 - 妥当ではないdl/dt/dd要素
 - figure要素内容にないfigcaption要素
 - 妥当ではないul/ol/li要素
 - 妥当ではない要素の入れ子
 - lang属性値とdir属性値のミスマッチ
 - 妥当ではない祖先要素をもつdiv要素
 - thead要素を含まないtable要素
 - table要素の入れ子
 - role属性値にheadingを指定しているにも関わらず、aria-level属性を指定していない要素
 - 装飾目的のものではないのに、role属性値imgを指定していないsvg要素
 - for属性を指定していないlabel要素
 - id/class属性における計算値の指定
 - role属性値presentationを指定した画像
 - セクショニング要素の誤用
 - レイアウト目的と思しき(spacer.gifなどの)画像
 - style属性
 - レイアウト目的ではないにも関わらずcaption要素を含まないtable要素
 - レイアウト目的と思しき(1行しか存在しない)table要素
 - 妥当ではないtable要素内容
 - scope/id属性を指定していないth要素
 - target属性値_blankを指定しているにも関わらず、rel属性でセキュリティに配慮していない要素
 
時代遅れ
アドバイス
- ユニークであるべきにも関わらず複数指定されたrole属性
 - 値が空もしくは空白文字のclass属性
 - 値が空もしくは空白文字のid属性
 - 祖先要素を同じくして複数存在するfigcaption要素
 - 要素内容の最初にも最後にもないfigcaption要素
 - ダウンロードを意図した、もしくは特殊なフォーマットのファイルへのリンク
 - 本来であれば非表示すべきと思しき(内容が空ではない)要素
 - mailtoスキームのリンク
 - 表示しているものとは別に存在する、非表示のmain要素
 - role属性値にsearchを指定すべきと思しき要素
 - href属性を指定していないa要素
 - src/href属性値のURLが、セキュアではない(HTTPスキームの)要素
 - placeholder属性をlabel要素の代わりにしていると思しき要素
 - required/aria-required属性を指定している要素
 - ボタンに見せかけた(role属性値buttonを指定した)a要素
 - レイアウト目的の(role属性値presentationを指定した)table要素
 - 新規タブ/ウィンドウを開くリンク
 - telスキームのリンク
 - scope属性を指定したth要素
 - 日付や時刻を記載しているはずの要素
 - alt/aria-label属性と一緒にtitle属性を指定した画像
 - video/audio要素(アクセシビリティ向上のための注意喚起)
 
a11y.cssに対する雑感
最新のHTML仕様に追いつけていない部分(例:妥当ではないtable要素内容で指摘しているthead/tfoot/tbody要素の序列)がありますし、どの指摘をどのレベルのものとして扱うかや、そもそも指摘内容として妥当か? という点で議論の余地はありますけど、技術的に面白い取り組みだと私は思いました。CSSセレクタの充実により、CSSだけでこれほど多くの潜在的な課題を指摘可能というのは、かれこれ20年以上にわたりWeb制作に携わってきた身からすると、少しばかり感動してしまう点です。
a11y.cssをそのまま活用しなくとも、a11y.cssを参考にプロジェクト固有のマークアップ品質チェック用CSS(や、同CSSを適用するブックマークレット)を作ってみると、面白いかもしれません。それだけであらゆる品質を網羅的にチェックするのは不可能にせよ、マークアップ工程における品質担保や効率化の一助として、プロジェクト固有のマークアップルールへの適合状況を簡単にチェックできるようになれば、きっと便利でしょう。
また冒頭で触れたように、a11y.cssは複数の言語に翻訳されています。サンタさんからのプレゼント代わりに、私のほうで本日までに日本語バージョンをリリースしようと思っていたのですけど、時間的に間に合いませんでした。申し訳ありません。本記事をきっかけとしてa11y.cssの翻訳に興味を持たれた方は、是非Translations · ffoodd/a11y.css Wikiを参照のうえ挑戦してみてはいかがでしょうか......良いクリスマスをお過ごしください。