トピックを検索
マウスでしか切り替えも拡大もできない商品写真ギャラリー
商品写真のサムネイルがクリックしか受け付けず、拡大もマウスの動きに頼っているうえ、ボタンにしてもどの写真を表示中かが伝わらない
<img class="thumb" src="mug-back-small.jpg" alt=""> 問題
キーボード利用者は1枚目以外の写真も写真の細部も見られず、スクリーンリーダーの利用者には、各サムネイルが何の写真か、どの写真を表示中かが伝わらない
あるショップがホーローマグを売っています。商品ページには大きな写真が1枚あり、その下に正面、側面、背面の3つのサムネイルが並びます。背面には「Dishwasher safe」「350 ml」という小さな印字があり、この大きさでは読めません。マウスなら問題なく使えます。最後のサムネイルをクリックすると背面の写真に変わり、写真の上でマウスを動かすと、ポインターの周りが拡大されて印字が読めます。
マウスから手を離してTabキーを押してみます。フォーカスはそのまま「カートに入れる」へ移ります。サムネイルはクリック処理を付けた画像で、フォーカスを受けないため、キーボード利用者が見られるのはマグの正面だけです。拡大は写真の上でマウスを動かすと始まる仕組みで、キーボードでは始められません。正しい写真を出せたとしても、小さな印字は読めないままです。
サムネイルを本物のボタンにしたギャラリーもあります。Tabで届き、Enterキーで写真も変わります。ところが画像のaltが空なので、どのボタンも「ボタン」としか読まれません。表示中の印はクラスで描いた枠線だけで、スクリーンリーダーには伝わらず、押して写真が変わっても何も読まれません。拡大にはやはりマウスが必要です。
達成基準2.1.1(キーボード)は、マウスでできることはすべてキーボードでもできるよう求めています。写真を切り替えるには画像をクリックしますが、画像はフォーカスを受けないので、Tabは止まらず、Enterキーで押す相手もありません。拡大は mousemove で始まりますが、このイベントはどのキーを押しても発生しません。W3Cの失敗例F54が挙げているのがまさにこの場合で、ポインティングデバイス専用のイベントハンドラーでしか機能を実行できない状態を指します。ここでの機能は、写真の細部を見ることです。
達成基準4.1.2(名前・役割・値)は、コントロールの名前、役割、状態を伝えるよう求めています。クリックできる画像にはボタンの役割がありません。alt="" の画像だけを入れたボタンには、役割はあっても名前がありません。さらにどちらも、表示中のサムネイルは枠線を描く is-current クラスでしか分からず、状態が伝わりません。画像をボタンにすればキーボードの問題は解決しますが、こちらは残ります。
サムネイルを押すと、フォーカスはサムネイルに残ったまま、ページの別の場所で写真が変わります。そのためスクリーンリーダー利用者には、何かが起きたことが伝わらない場合があります。どちらの基準も、この変化を読み上げることまでは求めていません。ただ、伝わるに越したことはないので、以下の修正では、カルーセルのガイドで新しいスライドを読み上げるのと同じように、控えめなライブリージョンで知らせます。
背面、ラベル、お手入れの説明など、1枚目にはない情報がほかの写真に写っていることはよくあります。マウスを使えない人には正面の写真しか見えず、ほかの写真があることに気づかない場合もあります。
10グループ中2グループに影響
画像で作ったサムネイルにはボタンの役割がないので、axeには調べる対象がありません。この診断が報告するのは、クラス名からサムネイルと判断でき、カーソルがポインターになり、フォーカスを受けず、近くにずっと大きな写真があって、ほかに写真を変える手段がギャラリーにないものです。キーボードで押せる前後のボタンが並ぶサムネイルは対象外です。FlexSliderのサムネイルも対象外です。スライダーが1つだけのページなら、初期設定のままで、どこにいても左右の矢印キーでスライドが変わるためです。サムネイルが名前のないボタンなら、axeが button-name を報告します。role="button" を付けたdivなら aria-command-name です。
次の2つは人の判断が必要なため、確認の手がかりとして報告します。1つは、どのサムネイルにも状態がないボタンの列です。aria-current がないことはコードで分かっても、ページがほかの方法で伝えているかまでは分かりません。もう1つは、マウスでの拡大を設定した写真で(Drift、elevateZoom、jQuery Zoom、Magentoの拡大鏡、Dawnのホバー設定が残す目印で判断します)、写真がリンクの中になく、近くに拡大や写真を開くと分かるコントロールがない場合です。自前で実装した拡大にはこうした目印がなく、どのチェックでも見つかりません。
手早く直そうとして各画像に tabindex="0" を足すだけでは、Tabで止まっても、EnterキーもSpaceキーも効きません。フォーカスで拡大が始まるようにしても同じことで、見たい部分へ表示を動かす手段がキーボードにはありません。
チェックツールに出るメッセージ
- axe DevTools
- ARIAコマンドにはアクセシブルな名前がなければなりません ARIA commands must have an accessible name
- ボタンには認識可能なテキストが存在しなければなりません Buttons must have discernible text
- Lighthouse
button、link、menuitem要素にユーザー補助機能向けの名前が設定されていません。button,link, andmenuitemelements do not have accessible names.- ボタンにユーザー補助機能名が指定されていません Buttons do not have an accessible name
- WAVE
- Empty button
試してみる
マグの背面にある小さな印字を、まずマウスで、次にTabキーだけで読んでみましょう
問題1: 最後のサムネイルをクリックし、写真の上でマウスを動かします。次にマウスから手を離してTabキーを押すと、フォーカスはサムネイルを飛ばして「カートに入れる」へ移ります。
問題2: Tabキーでサムネイルに届き、EnterキーやSpaceキーで写真が変わります。下の欄を見ると、どれも「ボタン」としか読まれず、表示中とも読まれません。拡大はマウスの動きに頼ったままです。
修正を適用します。 Tabキーで最後のサムネイルへ移動してEnterキーを押し、修正で加わった操作を使ってください。写真が大きくなったら、矢印キーで動かせます。
問題あり 修正できますか?
ホーローマグ
$24
スクリーンリーダーの読み上げ:
(Tabでギャラリーへ移動するか、サムネイルをクリック)
修正方法
キーボードで写真を切り替え、拡大できるようにする
マウスでしか使えないサムネイルと拡大
<div class="gallery"> <div class="photo-frame"> <img class="photo" src="mug-front.jpg" alt="マグの正面"> </div> <div class="thumbs"> <img class="thumb is-current" src="mug-front-small.jpg" alt="" data-photo="mug-front.jpg" data-alt="マグの正面"> <img class="thumb" src="mug-side-small.jpg" alt="" data-photo="mug-side.jpg" data-alt="マグの側面"> <img class="thumb" src="mug-back-small.jpg" alt="" data-photo="mug-back.jpg" data-alt="マグの背面"> </div></div>問題点5点
- サムネイルは
clickにしか反応しない画像なので、Tabで止まらず、キーボードでは別の写真を表示できません。 - 役割がなく、altも空です。
- 表示中のサムネイルの印は
is-currentクラスだけで、枠線を描いているにすぎません。 - 拡大は
mousemoveでしか始まらないので、キーボードからは細部を見られません。 - 新しい写真に変わっても、スクリーンリーダーには何も読まれません。
拡大ボタンとスクロールできる枠
<div class="gallery"> <button type="button" class="zoom">拡大</button> <div class="photo-frame" role="region" aria-label="拡大した写真"> <img class="photo" src="mug-front.jpg" alt="マグの正面"> </div> <p class="photo-count" aria-live="polite">写真3枚中1枚目:マグの正面</p> <div class="thumbs"> <button type="button" class="thumb" aria-current="true" data-photo="mug-front.jpg"> <img src="mug-front-small.jpg" alt="マグの正面"> </button> <button type="button" class="thumb" data-photo="mug-side.jpg"> <img src="mug-side-small.jpg" alt="マグの側面"> </button> <button type="button" class="thumb" data-photo="mug-back.jpg"> <img src="mug-back-small.jpg" alt="マグの背面"> </button> </div></div>修正の手順7ステップ
- 各サムネイルを、画像を中に入れた本物のボタンにします。Tabで届き、EnterキーとSpaceキーでも押せるので、キー操作の処理を書く必要はありません。
- 各サムネイルのaltに、どの写真かを書きます。ボタンの中身が画像だけなら、このテキストがボタンの名前になります。
- クリック処理の中で、表示中のサムネイルに
aria-current="true"を付けてほかから外し、スクリーンリーダーが「現在の項目」と読めるようにします。 - 枠線を
[aria-current='true']から描きます。これで見た目と読み上げが食い違いません。 - 必須ではありませんが、どの写真を表示中かを控えめなライブリージョンで伝えます。フォーカスを動かさなくても、押した結果が耳で分かります。
- 「拡大」ボタンを足します。スクロールできる枠の中で写真の幅を3倍にし、枠をTabの移動先にするので、矢印キーで写真の中を動けます。Tabで先に届くよう、ボタンは枠より前に置きます。
- マウスの動きに合わせた拡大は近道として残し、ボタンで拡大している間は止めます。
これで修正前の2つの問題がどちらも解消し、2.1.1と4.1.2を満たします。幅を3倍にしても細部が鮮明なように、十分に大きな画像ファイルを用意してください。
この方法を選ぶ理由:ジェスチャーは近道にし、唯一の方法にしない
どの方法でも基準を満たし、マウスを使う人のための拡大も残せます。違うのは、もっと見たいと思ったときに何が表示されるかです。拡大ボタンはその場で写真を大きくするもので、デザインで占める場所が最も少なくて済みますが、見える範囲は写真の枠の大きさのままで、スマートフォンでは狭くなります。ダイアログは写真に画面の大部分を使え、商品ページでよく見る形です。WooCommerceは、テーマがギャラリーの拡大とライトボックスを有効にしていれば、マウスでの拡大を残したまま、写真を開くコントロールを足します。ShopifyのDawnテーマも、初期設定ではボタンから写真を開きます。マークアップは少し増え、閉じるまでほかの部分は操作できません。リンクは数行で済み、壊れる心配もほとんどありませんが、ページから離れることになります。手間をかけられないとき、あるいはスクリプトが動かなくても大きな写真に届くよう、ダイアログの土台として選んでください。
ここで使う状態は、カルーセルの表示中のドットと同じ aria-current="true" です。一連の項目のうち、現在の1つを示します。aria-pressed では各サムネイルがトグルボタンになり、もう一度押すとオフになるように受け取られます。aria-selected はボタンには使えません。ShopifyのDawnテーマとSplideのナビゲーションモードも、ギャラリーのサムネイルに aria-current を使っています。
サムネイルに名前を付ける方法はほかにもあり、画像のaltを空にして aria-label="写真3:マグの背面" と書くこともできます。altならより少ない記述で同じことができ、ライブリージョンで読むテキストとしてもそのまま使えます。
画像そのものをクリックすると大きく開くメインの写真も、サムネイルと同じ理由で2.1.1を満たしません。ダイアログの修正のように横にボタンを置くか、写真を大きなファイルへのリンクで囲みます。リンクで囲むのはPhotoSwipeがマークアップとして求める形で、Fancyboxの例も同じ形です。スクリプトが読み込まれていればライトボックスが開き、読み込まれていなければファイルが開きます。写真の上のレンズはフォーカスを必要としないので、残してかまいません。
拡大の枠がTabの移動先になる必要があるのは、スクロールできる間だけです。そのため修正では、拡大したときに tabindex を付け、戻したら外します。何もしないのに止まる場所があると、キーボード利用者が通り過ぎる手間が増えます。
写真が多いギャラリーでは、サムネイルの列がスクロールし、専用の矢印が付くことがあります。その矢印も名前のあるボタンにし、見えていないサムネイルにフォーカスが移ったら、見える位置までスクロールするようにしてください。
デザインの案
ギャラリーの形は、小さな写真の列だけではない
マグのギャラリーを6通りに描きました。それぞれマウスで試してから、マウスを使わずにTabキーを押してみてください。4つはキーボードですべての写真を見られますが、2つはマウスでしか見られません。
デザインファイルで
- 表示中の印は色や薄さだけでなく、線、枠、塗りつぶしたピルなどの形で描く。
- 各サムネイルの横に「マグの背面」のように何の写真かを書く。スクリーンリーダーが読む名前になる。
- ポインターを追う拡大鏡があっても、マウスを使わない人のための拡大ボタンやリンクを横に描く。
- サムネイルにフォーカスの枠を描き、枠が切れないだけの余白をとる。
- ホバーで現れる矢印は、キーボードでフォーカスしたときとタッチスクリーンでの見え方も描くか、常に表示する。
合格
- すべての写真をページに並べる サムネイルをなくし、写真を大きく1枚、その下に2枚並べてページに置きます。切り替えるものも、表示中の印も要りません。各写真が大きなファイルへのリンクになり、キーボードから細部を見る手段にもなります。ページは長くなるので、「カートに入れる」ボタンは写真の横で見え続けるようにします。
- 文字で選ぶピル 写真の下に「正面」「側面」「背面」のピルを並べます。小さな写真を見分けなくて済み、ピルの文字がそのままスクリーンリーダーの読む名前になります。表示中のピルは紺で塗りつぶします(白と#2d3a55で11.36:1)。ほかのピルは枠線だけなので、色合いの違いだけに頼りません。
- 写真3枚中1枚目枚数を挟む左右の矢印 スマートフォンに写真の列を収める必要がありません。「2 / 3」を挟んで直径36pxの丸い矢印を2つ置きます。どの写真を表示中かを数字で示し、変わると控えめなライブリージョンで読み上げます。見たい写真へ直接は移動できず、順に送るしかないので、枚数の少ない商品に向いています。
- 表示中に線を引いた縦のサムネイル 写真の横にサムネイルを縦に並べ、表示中のものの左端に4pxの紺の線を引きます(サムネイルの背景#f1f3f6に対して10.22:1)。ほかのサムネイルは薄くしないので、見分けやすいままです。スマートフォンでは写真の下に並べます。
不合格
- マウスを載せるだけで変わる写真WCAG 2.1.1 マウスならクリックも要らず手軽です。しかし押すものがないので、Tabはサムネイルを飛ばし、キーボードでは最初の写真から変えられません。
- ホバーで現れる矢印WCAG 2.1.1 マウスを載せるまで写真がすっきり見えます。矢印は本物のボタンですが、隠れている間はフォーカスを受けないので、Tabは素通りし、キーボードではほかの写真を見られません。フォーカスでも表示するか、常に表示してください。
修正の確認
4項目、マウス不要
確認方法: キーボード、スクリーンリーダー、強制配色
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。ギャラリー、ライブラリー、テーマを変更した際は、再度確認します。
スクリーンリーダーでの aria-current="page"の読まれ方
制限
このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。扱うのは、サムネイルと拡大に届くか、サムネイルが何を伝えるかです。矢印とドットで切り替えるスライド形式のギャラリーは、キーボードやスクリーンリーダーで使えないカルーセルで扱います。ライトボックスのフォーカスと閉じ方については、背後にフォーカスが残るモーダルを参照してください。ドラッグ、ピンチ、傾きで回したり拡大したりする写真の表示は、ボタンで代われないピンチ・ドラッグ・傾きのジェスチャーで扱います。各写真のaltに何を書くかは、写真によって変わります。このガイドで求めるのは、サムネイルのaltで写真を区別できることと、写真が変わったら大きな写真のaltも合わせることだけです。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
EaseWebのサービス
修正した問題を、次のリリースで再発させない
このガイドのような修正方法を、コーディングエージェントが従うルールと、CIのチェックに組み込みます。あわせて定期的に、キーボードとスクリーンリーダーで手動の再テストを行います。