トピックを検索
ボタンに名前がなく、数を入力できない数量ステッパー
数量を変える−と+が名前のないアイコンボタンで、間の数字はただの文字だったり、数量欄のキー入力をスクリプトが止めていたりするため、スクリーンリーダーでは「ボタン」としか聞こえず、欲しい数を誰も入力できません。
<button type="button" class="step"><svg>…</svg></button> 問題
スクリーンリーダーの利用者にはどちらのボタンでマグが増えて、どちらで減るのかが分からず、誰も数量を入力できません。欄のキーが止められていると、キーボードの利用者は数量をまったく変えられません。
$18のホーローマグを売るネットショップのページです。「カートに入れる」の上に数量のステッパーがあり、丸い−のボタン、数字の1、丸い+のボタンが並んでいます。マウスなら問題なく使え、+を3回押すと数字は4になります。スクリーンリーダーを起動してTabで移動すると、「ボタン」、もう一度「ボタン」と聞こえます。2つを見分ける手がかりは−と+のアイコンだけで、どちらにも言葉はありません。間の数字はTabで止まらないので、押した後に今いくつなのかを伝えるものもありません。確かめるには、スクリーンリーダーの利用者はボタンを離れて、その行を読みに行く必要があります。数字を直接入力することもできません。カフェ用に10個買うなら、+を9回押すことになります。
同じショップの別の作りでは、数量は「数量」とラベルの付いたふつうの数値の入力欄で、端にブラウザーの小さな上下の矢印があります。文字や「-3」が入らないように、開発者がTab以外のすべてのキーを取り消しています。Tabで届き、スクリーンリーダーは「数量、スピンボタン、1」と読みますが、4と入力しても何も起きません。本来ブラウザーが数を増減させる上下の矢印キーも効きません。数を変えられるのは、マウスで小さな矢印を押したときだけです。
達成基準4.1.2は、すべての操作部品に、支援技術が読める名前があることを求めています。ボタンの名前は中身から決まりますが、ここでの中身はtitleも文字もないSVGだけです。そのため名前は空になり、スクリーンリーダーには役割しか読むものがありません。これは失敗例F68、つまりコード上で名前のない操作部品に当たります。−と+は図形として描かれているだけで文字ではないため、ブラウザーには読み取れません。数字は役割のない文字だけの span なので、ページを1行ずつ読んだときにしか読まれず、ボタンと一緒には読まれません。コード上でボタンと結び付けるものもありません。
達成基準2.1.1は、マウスでできることはすべてキーボードでもできることを求めています。2つ目の作りは、本来なら欄だけでこの基準を満たせます。ブラウザーの数値の入力欄には、文字の入力と上下の矢印キーでの増減が初めから備わっているからです。しかしブラウザーがキー本来の動作をするのは、ページの keydown の処理が終わった後です。その処理で preventDefault() を呼ぶと、動作は取り消されます。そのため矢印キーも含め、どのキーを押しても何も起きません。欄の端のスピンの矢印はブラウザーがポインター用に描くもので、フォーカスを受けないため、数を設定する方法はマウスしか残りません。キーを止めるのは文法上正しいスクリプト1行にすぎず、HTMLの側では防げません。
数量のステッパーは、カートへ進む途中にあります。読み上げられない、または数を設定できないステッパーがあると、購入はそこで止まるか、違う数のまま注文されてしまいます。カートの各行にも同じステッパーが置かれるため、行ごとに名前のないボタンが2つずつ増えます。
10グループ中3グループに影響
- 全盲 (影響あり)
- 弱視 (影響なし)
- 色覚 (影響なし)
- ろう (影響なし)
- 難聴 (影響なし)
- 発話 (影響なし)
- 手の操作 (影響あり)
- 届く範囲・力 (影響あり)
- 認知 (影響なし)
- 光過敏 (影響なし)
- 視覚を使わない スクリーンリーダーの利用者には「ボタン」が2回聞こえるだけで、どちらでマグが増え、どちらで減るのかが分かりません。押した後も新しい数は伝わらず、確かめるにはボタンを離れて、その行を読みに行く必要があります。欄のキーが止められていると、スピンの矢印はマウスにしか反応しないため、数量はまったく変えられません。
- 手の操作が限られる キーボードやスイッチの利用者は数量を入力できず、10個なら+を9回押すことになります。欄のキーが取り消されていると、数量はまったく変えられません。音声操作の利用者には、どちらのボタンにも口にできる名前がありません。
- 届く範囲・力が限られる 手にふるえがある人や握力の弱い人は、1個ごとに1回押す操作で疲れます。キーが止められていると、残る方法は欄の端の小さなスピンの矢印だけで、狙いを外しやすくなります。
axeは1つ目の作りのボタンを名前がないもの(button-name)として報告しますが、間の数字を入力できないことは分かりません。数字の入った span は正しいマークアップだからです。2つ目の作りには、自動チェックは何の問題も見つけません。マークアップはラベル付きの数値の入力欄で、正しく書かれており、キーが止められていることはキーを押して初めて分かります。EaseWebの診断は、横にステッパーのボタンがない数値の入力欄ごとに、矢印キーを押して数字を入力し、どれでも値が変わらない欄を報告します。自動チェックの指摘を直すようにコード生成AIに頼むと、各ボタンを働きではなく絵柄で名付けたり(「+」「マイナス」)、名前を付けただけで終わったりすることがあり、数字は入力できないまま残ります。数値の入力欄に文字が入らないようにしたいと頼むと、keydown を取り消す方法を提案することがあり、矢印キーと数字まで一緒に止めてしまいます。
試してみる
マウスを使わずに数量を4にしてください。Tabでステッパーへ移動し、4と入力するか、ボタンや上矢印キーを使います。
下の欄に、スクリーンリーダーの読み上げが出ます。問題1では、2つのボタンは何と読まれますか?数字は入力できますか?問題2では、4と入力するか上矢印キーを押してから、マウスで欄の小さな矢印をクリックしてみてください。
問題あり 修正できますか?
ホーローマグ $18
スクリーンリーダーの読み上げ:
(Tabでステッパーへ移動)
修正方法
−と+に何をするかを表す名前を付け、数量を、入力と矢印キーを受け付けるラベル付きの数値の入力欄にします。
- 1ステッパーの各ボタンに、何をするかを言葉で表す名前がある。
- 2数量は、入力できるラベル付きの欄である。
- 3数値の入力欄が受け付けるキーを、スクリプトが取り消さない。
表示されただけの数字を挟む、名前のないアイコンボタン
<form class="buy" action="/basket" method="post"> <span class="qty-label">数量</span> <div class="stepper"> <button type="button" class="step" data-step="-1"> <svg class="icon" viewBox="0 0 16 16">…</svg> </button> <span class="qty">1</span> <button type="button" class="step" data-step="1"> <svg class="icon" viewBox="0 0 16 16">…</svg> </button> </div> <input type="hidden" name="quantity" value="1"> <button type="submit">カートに入れる</button></form>数値の入力欄を挟む、名前の付いたボタン
<form class="buy" action="/basket" method="post"> <label for="qty" class="qty-label">数量</label> <div class="stepper"> <button type="button" class="step" data-step="-1"> <svg class="icon" viewBox="0 0 16 16" aria-hidden="true">…</svg> <span class="visually-hidden">数量を減らす</span> </button> <input id="qty" name="quantity" type="number" min="1" max="10" value="1"> <button type="button" class="step" data-step="1"> <svg class="icon" viewBox="0 0 16 16" aria-hidden="true">…</svg> <span class="visually-hidden">数量を増やす</span> </button> </div> <button type="submit">カートに入れる</button></form>各ボタンの中身はtitleのないSVGだけなので、名前は空になり、スクリーンリーダーは「ボタン」としか読みません。数量は span と隠しinputで、ボタンと一緒には読まれず、入力もできません。
各ボタンは「数量を減らす、ボタン」のように働きを伝え、アイコンは名前に何も加えないよう読み上げから外れます。数字は本物の入力欄になり、「数量、スピンボタン、1」と読まれ、10と直接入力でき、上下の矢印キーで増減できます。フォームが送信するのもこの欄なので、隠しinputは不要になります。stepUp() と stepDown() は min と max で止まるため、ボタンで1未満や10より多くにはなりません。丸いボタンのデザインはそのまま残せます。デザインがそのボタンだけを見せる場合は、ブラウザー自身のスピンの矢印をCSSで隠しても構いません。矢印キーは矢印の絵ではなく欄に備わっているので、引き続き使えます。
3つともボタンに名前を付けます。初めの2つは、さらに数量を、入力と矢印キーでの増減ができる欄にします。数値の入力欄を挟む名前の付いたボタンは、デザインどおりの見た目のまま、数を入力できるようにします。大きな丸いボタンが大切な場合に選びます。スマートフォンでは、ステッパーの中でいちばん押しやすいのがこのボタンなので、たいていは大切です。ブラウザーの数値の入力欄だけの方法はコードが最も少なく、キーが止められていた欄への素直な修正です。デスクトップのカートの表や、一度に何十個も注文する業務用の注文フォームのように、ふつうの入力欄がデザインに合う場合に選びます。ボタンに名前を付けるだけの方法は最も手早く、自動チェックの指摘も消えますが、数字は入力できないままです。修正そのものではなく、1つ目の方法へ向かう途中の一歩と考えてください。
ページに組み込んだ後のステッパーの動作は、次の点で決まります。
- カートでの名前:どの行にもステッパーがあると、ボタンの一覧には「数量を減らす」「数量を増やす」が何度も並ぶ。名前と欄のラベルに商品名を入れる(「数量を増やす、ホーローマグ」)。見えている言葉の後に、視覚的に隠したテキストで加える。
- 最小と最大の数量:1と10でもボタンは有効のままにする。そこでは
stepDown()とstepUp()が何もしないだけだからである。フォーカスのあるボタンを無効にすると、フォーカスはページ全体に移ってしまう。見つからず理由も分からない無効なボタンを参照。 - 押したときに伝わること:フォーカスはボタンに残るため、スクリーンリーダーは欄の新しい数を読まない。ただし欄は、Tabの順序でボタンのすぐ隣にある。利用者が気づきにくいとテストで分かったら、「数量4」のような短い控えめなステータスで補う。「カートに入れる」でカートがどう変わったかを伝えることは、カートへの追加などの操作結果を音声で知らせるという、別のトピックになる。
- 範囲外の数:
maxが10の欄にも、30と入力することはできる。フォームを送信するとブラウザーが受け付けず、理由を伝える。ページが自分で数を直す場合は、黙って変えず、欄の横でそう伝える(「残り10個」)。
スクリプトがほかのキーと一緒にTabまで取り消すと、フォーカスは欄からまったく出られなくなります。これは別の問題です。フォーカスが抜け出せないエディターや埋め込み部品を参照してください。文字を入れさせないために、欄を readonly にすることも避けます。止められたキーと同じく、入力も矢印キーも使えなくなり、ほとんどのブラウザーではスピンの矢印まで効かなくなります。
ショップのテーマやデザインシステムのステッパーはさまざまです。ボタンに名前はあっても数字はただの文字で表示するもの、入力欄はあってもアイコンに名前がないもの、文字を入れさせないためにキーを止めるものもあります。コンポーネントの説明をうのみにせず、ブラウザーの開発者ツールのアクセシビリティ欄で、各部分が実際に何として伝わっているかを確かめてください。
AI コーディングアシスタントで修正しますか? このガイドを Markdown で取得、または全ガイドをコーディングエージェントで使う。
デザインの案
軽やかで今風のステッパーでも、読み上げられ、入力できます。
マグの数量を4通りに描きました。それぞれをクリックしてから、マウスを使わずにTabで移動してみてください。3つはキーボードで設定でき、読み上げで何の部品かが分かります。1つはポインターにしか反応しません。
デザインファイルで
- 各ボタンの横に名前を書く。たとえば「数量を減らす」「数量を増やす」、ごみ箱なら「削除」。
- 数字は入力できる欄として描き、カーソルとフォーカスの枠が付いた状態も描く。
- デザインに表示しない場合も、数量に「数量」というラベルを付ける。
- 最小と最大の数量でのステッパーも描き、どちらのボタンも残しておく。
合格
- 真ん中の数字を入力できる1つのピル −、数字、+を、高さ46pxの1つのピルにまとめました。ピルは#f1f3f5の淡い灰色で、#8a929cの縁(白に対して3.15:1)があり、ボタンはその中の白い円です。数字は自分の枠を持たない入力欄で、クリックかTabでカーソルが入り、ピル全体にフォーカスの枠が付きます。
- ホーローマグ $181のときは−の代わりにごみ箱 カートの行で、数量が1のときは−がごみ箱に変わり、同じ場所で商品を削除できます。名前もアイコンと一緒に「数量を減らす」から「ホーローマグを削除」に変わり、商品の代わりに表示される行で「元に戻す」を選べます。
- 数量のドロップダウン 大手のショップによくある、紺の縁のピルに「数量 1」と表示する形です。見た目を整えてあるだけで、中身はブラウザー自身のドロップダウンです。タップでシステムの一覧が開き、Tabで移動して矢印キーで選べ、ラベルと値が読み上げられます。上限が小さい場合に向いています。10個ほどを超えるなら、長い一覧より入力のほうが速くなります。
不合格
- 数量 1数字の横に重ねた小さな矢印WCAG 2.1.1 小さくまとまったカウンターです。枠の中の数字の横に上下の矢印が重なっていますが、矢印はクリックにしか反応しないアイコンです。Tabでは素通りし、入力もできず、スクリーンリーダーには操作できる部品が見つからないため、ポインターがなければ数は1のままです。
修正の確認
マウスを使わない5つの確認
確認方法: キーボード、スクリーンリーダー、タッチ
OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。ステッパーのコンポーネントやテーマを変更した際は、再度確認します。
制限
このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。数値の入力欄の役割はスクリーンリーダーによって呼び方が異なり、ラベルより先に数を読むものもあります。人数、泊数、時刻を設定するステッパーも同じ作り方ですが、サイズのように言葉を順に切り替えるステッパーは別の部品で、selectやラジオボタンのグループを使います。トラックの上を動かす部品ならドラッグでしか動かない範囲スライダーを、ヘッダーの検索やメニューのような、ページのほかの場所のアイコンボタンなら名前がないアイコンだけのボタンを参照してください。対象とする支援技術で、商品ページからカートまでの操作全体を確認してください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
コードを更新しても、使いやすさを保つために
ガイドの内容を、コーディングエージェントやCIで使える開発ルールにまとめます。更新後は、キーボードとスクリーンリーダーで再テストし、問題が再発していないか確認します。