アクセシビリティチェックってどうやってるの?ということで、実際にやってみた。(その1)

ツイッターアクセシビリティ向上日誌2【目視試験編】‐Akira Tsuda Portfolio and Blogというのを見かけて、そういえばアクセシビリティチェックって何をどうしているのかという話をウェブ上でほとんど見かけない(というか自分は知らない)ので、思い切ってチェックの過程や考え方を書いてみようかなと。

チェック対象のサイトを作った@HeldaForStudy氏に尋ねたところ、題材として使ってよいという返事をいただいたので、「アトリエ金工やまぐち」のサイト1ページをチェックしてみることにします。

対象ページはBasic認証がかかっているので、アクセシビリティ向上日誌1【各種ツール評価編】からたどってください。 @HeldaForStudy氏はレベルはA*1でチェックしたとのことなので、チェック基準はWCAG 2.1レベルAでチェックすることにしましょう。 わたしは普段はCOB-CHAを使っていないので、ページの頭から問題点を挙げていくスタイルで。

なお、このページの目的はアクセシビリティチェックにどう取り組んでいるのかを説明するためであって、氏の制作したサイトやチェック結果にネガティブなことを言いたいわけではないので、そこは念のため記載しておきます。 また、チェックに抜け漏れ、誤りがある可能性があることもお断りしておきます。

機械検証(ツールによる検証)について

業務ではNu Html Checker*2axe-coreを利用した社内ツールでぱぱーっとチェックしますが*3、今回はアクセシビリティ向上日誌1【各種ツール評価編】で既にチェックされているので結果を改めてここで書く必要はないでしょう。

なお、axe DevtoolsLighthouseも中身はaxe-coreなので、どちらかお好きな方を使えばよいかと(axe-coreのバージョンが違ったりするかもなので、違う結果が返ってくるかもしれないですけど)

ところで、よくある誤解としてNu Html Checkerのエラーは全部SC 4.1.1「構文解析*4の問題とすることがあるみたいですが、それは誤りです。SC 4.1.1*5

達成基準 4.1.1 構文解析 (レベル A): マークアップ言語を用いて実装されているコンテンツにおいては、要素には完全な開始タグ及び終了タグがあり、要素は仕様に準じて入れ子になっていて、要素には重複した属性がなく、どの ID も一意的である。ただし、仕様で認められているものを除く。

とあるように、タグが壊れてない、要素が誤った入れ子になっていない、開始タグ内に同一属性が存在しない、IDが一意(重複したID値がない)の4つです。…まあ、達成基準の注記にあるとおり、

HTML 又は XML を使用するすべてのコンテンツでは、この達成基準は常に満たされているとみなすべきである。

というように(WCAG 2.2を契機に)明示されたので、SC 4.1.1は常に満たされているものとして扱います。Nu Html Checkerの報告は概ね達成基準の問題にならないことの方が多いですが*6、達成基準上の問題となるのであれば、ほとんどの場合はSC 1.3.1「情報及び関係性」かSC 4.1.2「名前 (name)・役割 (role)・値 (value)」で判断することになるので、(特にこれからアクセシビリティチェックをするという人は)忘れて大丈夫でしょう*7

HTMLのコンテンツモデルの違反は、情報構造の問題ですから、SC 1.3.1としてマークしていきます。

達成基準 1.3.1 情報及び関係性 (レベル A): 何らかの形で提示されている情報、構造、及び関係性は、プログラムによる解釈が可能である、又はテキストで提供されている。

目視検証について

本題に入る前に、COB-CHA、いいかえるなら実装チェックリストをどうして使っていないのか、という話をしておきましょう。WCAG 2.1解説書のWCAG 達成基準の達成方法を理解するでは

達成方法は、参考情報である。つまり、達成方法は必須要件ではない。WCAG 2.1 への適合を判断する根拠は、WCAG 2.1 で規定している達成基準であり、達成方法ではない。

とあります。つまりTechniques for WCAG 2(日本語訳名でいう「WCAG達成方法集」)は、参考情報であって、WCAG 2の達成基準を満たしているかどうかだけが判断基準です。また「その他の達成方法」にあるように、

W3C の WCAG 2.1 達成方法集文書にある達成方法に加えて、WCAG 達成基準を満たすその他の方法がある。W3C の達成方法は包括的なものではなく、より新しい技術や状況をカバーしていないかもしれない。

つまり、必ずしも達成方法(Techniques)を使ってWCAG 2を満たす必要はなく、Techniquesにはない別の方法で達成基準(SC)を満たしてしまっても問題ない、ということになります。実際にアクセシビリティチェックをこなしていけばわかりますが、チェックリストで判断するのはものすごく窮屈です。

前置きはさておき、中身を見ていきましょう。

ルーセルの問題

まず目に付くのは、カルーセルが止まらない問題ですね。SC 2.2.2「一時停止、停止、非表示」の問題ですが、これは@HeldaForStudy氏も問題点としてあげているとおりです。ちなみにSC 2.2.2は非干渉の達成基準ですので、WCAG2の観点では致命的…と評価されることになります。

swiperの評価をするのが面倒ですが、一応中身を見ておきましょう…

<ul class="swiper-wrapper section-top__swiper-wrapper" id="swiper-wrapper-309340565d92446a" aria-live="off" style="transition-duration: 0ms;">
<li class="swiper-slide section-top__swiper-slide swiper-slide-prev" role="group" aria-label="1 / 5" data-swiper-slide-index="0" style="width: 1648px; opacity: 0; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;">
...
</li>
<ul>

となっているわけですが、axeが指摘するとおり、

リスト要素内に許可されていない直接の子要素が存在します: [role=group]

ということですが、仕様に沿って何がどうダメなのかを確認しましょう。

HTMLのネイティブロールは、ARIA in HTML仕様で定義されています。これによると、ullistlilistitemを持ちます。ところが、ここでのコードは<li ... role="group">となっており、ロールが上書きされています。つまり親子関係としては

  • list
    • group

というようになっているわけですが、WAI-ARIA仕様 *8によればlistロールは、listitemロールしか持てません(これは、HTMLの<ol><ul><li>しか持てないのと同じ)。ですから、ARIA仕様違反、つまり情報構造としての誤りとなるため、SC 1.3.1の問題となります(axeの報告どおり)。

パッチ的な修正方法としてはrole="group"を削除すればそれでよいでしょう。根本的にswiperが悪いので、別のライブラリを使用するのを推奨します(@HeldaForStudy氏が言及しているとおり、Splideを使うのも一つの手かもしれません。ただ、実装にも依るのでアクセシビリティ上の問題が解決するのかは、チェックしてみないと何ともいえません)。個人的にはカルーセルは単なるリストの亜種でしかないと思っているので、あれそれとrole属性を付けなくといいのではと思いますけど。

ルーセルのスライドの中身としては、

<img class="section-top__swiper-img-pc" src="assets/img/michiyo/vase19-pc.jpg" alt="山口みちよ「(作品名)」">

というように提示されていますが、これは代替テキストが視覚以上の情報を含んでしまう(言いかえると、画像だけでは作品名は伝わらない)ので、作品名を提供したい(情報を持つ画像である)というのであれば、目で見えるようにテキストで提供するのが適切でしょう。SC 1.1.1「非テキストコンテンツ」の問題としてマークします。ただまあ、(後述する)「日常に火を灯す」とロゴの画像の背景となっていると捉えると、単なる装飾画像と捉えるのが適当かもしれません。

余談ですが、W3C WAIのaltディシジョンツリーの日本語訳が最近公開されたので、代替テキストに悩んだら初手としてこちらを当たるのもよいでしょう。

ルーセルのボタンのコントラスト比(SC 1.4.11)であったり、フォーカスが見えなかったり(SC 2.4.7)、リードテキスト「日常に火を灯す」のコントラスト比(SC 1.4.3)が気になるところですが、いずれもレベルAAの問題です(今はレベルAで見ているのでスルー)。ちなみに、ロゴはコントラスト比の達成基準の例外となることに注意しておきましょう。

ああでも、カルーセルのボタンとしては、

<span class="swiper-pagination-bullet" tabindex="0" role="button" aria-label="Go to slide 1"></span>

日本語のページなのにaria-label属性によるアクセシブルな名前が英語なのは微妙なので、SC 4.1.2「名前 (name)・役割 (role)・値 (value)」の問題としてマークしちゃいましょう(まあ<span>の中身が空っぽなのも気にはなりますが、目をつむっておきましょう)。

h1見出しの検討

h1見出しのテキスト(HTMLソースは改)はこういう格好ですが

<h1 class="section-top__lead">
  日常に火を灯す
  <img src="assets/img/logo1.png" alt="アトリエ金工やまぐち" loading="lazy">
</h1>

キャッチコピー「日常に火を灯す」は構造的には見出しではないのでh1は不適当

と@HeldaForStudy氏は評価しているものの、リードテキストをh1に含めること自体は不自然ではないと思います。どうしても見出し要素に入れたくないということであれば、

<header>
 <p>日常に火を灯す</p>
 <h1><img src="assets/img/logo1.png" alt="アトリエ金工やまぐち" loading="lazy"></h1>
</header>

というのもなくはないですが、スクリーンリーダーの見出しジャンプを考えると上策だとは思えず、今のテキストの入れ方のままでよいと個人的には思います。

あと、h1がある時点でSC 2.4.1ブロックスキップ」は自動的に満たされます。説明はブロックスキップを考える | Accessible & Usableあたりを読んでもらうとよいかなと。

メニュー

HTMLソース順という意味ではちょっと前後しますが、PC幅だと下スクロールしてからはじめて(画面左上の)サイドバーが出現する一方で、HTMLソースとしては<header>として<body>先頭に記述されているために、順方向のキーボードフォーカス移動でたどり着けない、という問題があります。SC 2.4.3「フォーカス順序」というよりかはむしろ、根本的にはHTMLソース上の提示順に問題があるので、SC 1.3.2「意味のあるシーケンス」の問題としてマークしておきましょう。(ワンソースで記述することを考えると、構造として破綻してしまうか…)

スクリーンショット
Firefoxの開発者ツールでタブ順序を表示させて雑に取ったスクリーンショット。フォーカス順序として難しいものが…。

SP(スマートフォン)幅ですと、ハンバーガーメニューとなりますが(下記ソース)、

<div id="open-button" class="open-button">
<span class="open-button__line1"></span>
<span class="open-button__line2"></span>
<span class="open-button__menu">menu</span>
</div>

マウスでクリックできてもキーボードで押下できない(SC 2.1.1「キーボード」の問題)、「ボタン」であることがスクリーンリーダーのような支援技術に伝わらない(SC 4.1.2「名前 (name)・役割 (role)・値 (value)」の問題)という状況です。まあネイティブの<button>なりを使ってくださいということですね。実装例は純粋なハンバーガーメニューってわけでもないのでなんともですが、Webアプリケーションアクセシビリティ──今日から始める現場からの改善 (WEB+DB PRESS plus)の「5.7 ハンバーガーメニュー」に任せます。

「閉じる」ボタンも、ボタンの役割と名前がない(SC 4.1.2)のと、表示上はメニューの末尾にある一方で、HTMLソース上はメニューよりも前にあるのでキーボードで移動できません(SC 1.3.2)。

いずれにせよ

1. メニューをサイドバーではなくヘッダとして設置

と最初の改善点として挙げられているので、改修で改善されるでしょう。。

Instagramの項目

<li class="sidebar__navigation--instagram">Instagram
  <p><a href="https://www.instagram.com/kenzo_kennkenn/" rel="noopener" target="_blank"><img src="assets/img/icon-insta.png" alt="Instagram-堅造" loading="lazy"><span class="sidebar__navigation-yugothic"></span>堅造</a></p>
  <p><a href="https://www.instagram.com/kinkou_yamaguchi/" rel="noopener" target="_blank"><img src="assets/img/icon-insta.png" alt="Instagram-みちよ" loading="lazy"><span class="sidebar__navigation-yugothic"></span>みちよ</a></p>
</li>

altは適切ではないと言えそうです(SC 1.1.1「非テキストコンテンツ」)。既に先行してInstagramというテキストがあって、人名も<img>の後で提供されているために、「大事なことなので2回言いました」になってしまうことから、画像は装飾的として代替テキストを空にする(alt="")のがよいかと。

リスト構造は趣味が入ってきますので、達成基準上(SC 1.3.1「情報及び関係性」)の問題とまではならない理解ですが、リストの入れ子にするとすっきりするとは思います。こういう感じでしょうか。(わかりやすさのため構造だけ記載)

<li class="...">Instagram
  <ul>
    <li><a href="..."><img src="..." alt=""><span aria-hidden="true" class="..."></span>堅造</a></li>
    <li><a href="..."><img src="..." alt=""><span aria-hidden="true" class="..."></span>みちよ</a></li>
  </ul>
</li>

リスト項目内で先行する画像を装飾とするならば、3点リーダーも装飾と捉えるのが自然かと思いますので、付け焼き刃的(あんまり好きじゃない)ですが、aria-hidden="true"とするのがよいでしょうか(SC 1.3.1の観点から)。いずれにせよ、(コロン「:」的な)3点リーダーの意味を伝えるのはこの文脈だとナシになるかと思いますので。

画面右上バナー

SC 2.4.4「リンクの目的 (コンテキスト内)」として挙げられていますが、特に問題ないという認識です。むしろ、キーボードのフォーカス移動のことを考えるとHTMLソース上でどこで提供すればよいのかに頭を抱える感じでしょうか…(SC 1.3.2として)。

小まとめ

まあ予想はしていましたが、ヘッダーとファーストビューで力尽きましたね(実際の業務にアクセシビリティチェックでもトップページは作業量として「重い」です)。その2に続きます

*1:WCAG 2.0なのか2.1なのかがわかりませんが、まあどっちでも大差ないといえばないので

*2:勤務先では社内にサーバーが立てられています

*3:miCheckerは使っていません

*4:Success Criteria、達成基準のこと。漢字を打つのが面倒なので、SCとします

*5:W3Cの文書は基本的に日本語訳があればそれを張っていきます

*6:HTMLの品質を測るものであって、アクセシビリティチェックのためのツールではないですので

*7:WCAG 2 FAQ How and why is success criteria 4.1.1 Parsing obsolete?がそう言っているように

*8:なんでリンクがWAI-ARIA 1.3なの?というツッコミがありそうですが、訳者の都合です

(メモ)ウェブアクセシビリティについて、改正障害者差別解消法はいったん脇に置いた方がいいんじゃないかみたいな話。

ウェブアクセシビリティにフォーカスを当てたいときに、障害を理由とする差別の解消の推進に関する法律(障害者差別解消法)でもって、「合理的配慮」(義務)の事前的改善措置としての「環境の整備」(努力義務)という論法がわかりにくすぎると思っており、だからこそ不正確な話が出てくると思うんですよね。

なので、障害者による情報の取得及び利用並びに意思疎通に係る施策の推進に関する法律(障害者アクセシビリティ・コミュニケーション施策推進法)でもって話を進めるのがいまのところはシンプルなんじゃないですかね。通称にアクセシビリティって入ってますし。

(事業者の責務)
第五条 事業者は、その事業活動を行うに当たっては、障害者がその必要とする情報を十分に取得し及び利用し並びに円滑に意思疎通を図ることができるようにするよう努めるとともに、国又は地方公共団体が実施する障害者による情報の取得及び利用並びに意思疎通に係る施策に協力するよう努めなければならない。

(障害者差別解消法の「環境の整備」と同じ)努力義務であって、だから何がどうなるというわけではないのですけども、ウェブにおける"障害者が必要とする情報を十分に取得、利用できるようにする"というのは、ウェブアクセシビリティのことと解釈できるわけです。この法律にもあるとおり努力義務としてがんばりましょう、で今のところはいいと思うんですよね。まあ、がんばりましょうというかけ声だけで、何をどうがんばるのかというのは(やっぱり法律上は)ひとことも書かれてないわけなんですけども*1

このあたりが高齢者、障害者等の移動等の円滑化の促進に関する法律バリアフリー法)と比較して、とても物足りないですよね(例としてバリアフリー法だと、法令で指定する建築物にはスロープを設けて、スロープの勾配角度はここまで、というのが定められている*2)。情報アクセシビリティに関しては、理念法だけは謎に存在するんですよねぇ…。たとえばユニバーサル社会の実現に向けた諸施策の総合的かつ一体的な推進に関する法律とか。

(定義)
第二条 この法律において、次の各号に掲げる用語の意義は、当該各号に定めるところによる。
(中略)
三 ユニバーサル社会の実現に向けた諸施策 全ての障害者、高齢者等が、基本的人権を享有する個人としてその尊厳が重んぜられ、その尊厳にふさわしい生活を保障される権利を有することを前提としつつ、障害者、高齢者等の自立した日常生活及び社会生活が確保されるようにするために、ユニバーサル社会の実現に関する国際的動向を踏まえ、次に掲げる事項を達成することを目指して行われる諸施策をいう。
(中略)
ニ 障害者、高齢者等が、円滑に必要な情報を取得し、及び利用することができること。

(ユニバーサル社会の実現に向けた諸施策の策定等に当たっての留意)
第八条 国及び地方公共団体は、ユニバーサル社会の実現に向けた諸施策の策定及び実施に当たっては、次に掲げる事項に特に留意しなければならない。
(中略)
四 障害者、高齢者等の言語(手話を含む。)その他の意思疎通のための手段並びに情報の取得及び利用のための手段を確保すること。

まあ、対象が行政なので、だからどうしたって感じですけど。というか障害者基本法では、

(情報の利用におけるバリアフリー化等)
第二十二条 国及び地方公共団体は、障害者が円滑に情報を取得し及び利用し、その意思を表示し、並びに他人との意思疎通を図ることができるようにするため、障害者が利用しやすい電子計算機及びその関連装置その他情報通信機器の普及、電気通信及び放送の役務の利用に関する障害者の利便の増進、障害者に対して情報を提供する施設の整備、障害者の意思疎通を仲介する者の養成及び派遣等が図られるよう必要な施策を講じなければならない。
2 国及び地方公共団体は、災害その他非常の事態の場合に障害者に対しその安全を確保するため必要な情報が迅速かつ的確に伝えられるよう必要な施策を講ずるものとするほか、行政の情報化及び公共分野における情報通信技術の活用の推進に当たつては、障害者の利用の便宜が図られるよう特に配慮しなければならない。
3 電気通信及び放送その他の情報の提供に係る役務の提供並びに電子計算機及びその関連装置その他情報通信機器の製造等を行う事業者は、当該役務の提供又は当該機器の製造等に当たつては、障害者の利用の便宜を図るよう努めなければならない。

というのがあり。昭和45年(1970年!)から「情報の利用におけるバリアフリー化」というコアなところはそもそも存在して、平成23年(2011年)の改正で加筆されたものの、障害者基本法の枠組みとしてはまあ変わらないよね、という。ただ、障害者基本法の第22条3から、障害者アクセシビリティ・コミュニケーション施策推進法の第5条でアクセシビリティやっていきましょうというのは拡大されたようにも見えるので、前進もとい漸進しているといえばそうなのかもしれません。

障害者アクセシビリティ・コミュニケーション施策推進法の10条には次のようにありますので、まあ情報、とくにウェブアクセシビリティについて具体的になにをどうしましょうという、バリアフリー法と対になるような法律を作りましょうといういつもの締めということで*3

(法制上の措置等)
第十条 政府は、障害者による情報の取得及び利用並びに意思疎通に係る施策を実施するため必要な法制上又は財政上の措置その他の措置を講じなければならない。

*1:それはそれとして、国の施策に協力するように努めよとしれっと書いてあるのはこれは…って感じがしたりしなかったり

*2:ちょっと古いですけどハート のあるビルをつくろうあたりが参考になるでしょうか

*3:芸がない…