トピックを検索
タッチ画面のある端末ではタップでしか押せないボタン
ページがタッチ画面の有無を調べ、あればclickの代わりにtouchendだけを待つため、マウスでクリックしてもEnterキーを押しても何も起きない
'ontouchstart' in window ? 'touchend' : 'click' 問題
タッチ画面付きのノートパソコンやキーボードを付けたタブレットで、マウスやキーボードでは「絞り込み」を開けず、ChromeとEdgeでは音声でも開けない
あるショップのマグカップ一覧には、上に「絞り込み」ボタンがあり、押すと色を選ぶパネルが開きます。以前のスマートフォンのブラウザーは、ダブルタップでの拡大に備えて、タップから約300ミリ秒待ってからクリックを送っていました。タップの反応を速くするため、このショップのスクリプトは、ブラウザーがタッチに対応しているかを調べ、対応していれば click の代わりに touchend を待ちます。スマートフォンでは、指を離した瞬間に「絞り込み」が開きます。
タッチ画面付きのノートパソコンでも、この判定は真になります。タップで「絞り込み」を開き、トラックパッドで色を選んでから、パネルを閉じようと「絞り込み」をクリックしても、何も起きません。キーボードを使う人がTabキーで「絞り込み」に移ってEnterキーを押しても、何も起きません。ChromeやEdgeでは、音声操作で「絞り込みをクリック」と言っても同じです。開け閉めできるのは、画面に触れた指だけです。
レベルAAAのWCAG 2.5.6「入力メカニズムの共存」は、プラットフォームで使える入力方法をコンテンツが制限しないことを求めています。例外は、制限が不可欠な場合、セキュリティのために必要な場合、利用者の設定を尊重するために必要な場合だけです。タッチ画面付きのノートパソコンでは、タッチ、トラックパッドやマウス、キーボードを同時に使え、利用者はいつでも持ち替えられます。W3Cは、このパターンを失敗例F98として挙げています。Touch EventsのAPI、メディアクエリーの pointer: coarse、navigator.maxTouchPoints などでタッチ画面を見つけ、タッチ専用のリスナーを選ぶものです。ここではどの例外にも当たりません。絞り込みのパネルにタッチが不可欠な理由はなく、この判定はセキュリティとも、利用者が選んだ設定とも関係がありません。
'ontouchstart' in window で分かるのは、ブラウザーがタッチイベントに対応していることだけです。タッチ画面付きのノートパソコンのChromeとEdgeは対応しており、WindowsとLinuxのFirefoxもタッチ画面を見つけると対応します。スマートフォンやタブレットのブラウザーは、ほかに何をつないでいても対応しています。マウスが送るのはマウスのイベントと click で、touchend は送りません。フォーカスしたボタンでのEnterキーとSpaceキーも同じです。スクリーンリーダーや音声操作がブラウザーのアクセシビリティの仕組みを通してボタンを押すと、ChromeとEdgeではマウスのイベントと click が届きます。Firefoxは、タッチイベントが有効なら touchstart と touchend も一緒に送るため、こうした押下でもパネルが開きます。そのため、ChromeとEdgeでは指以外の押し方がすべて、Firefoxではマウスとキーボードが、誰も待っていないクリックとしてページに届きます。Touch Eventsの仕様は、まさにこの判定を避けるよう書いています。タッチイベントに対応していても、タッチ画面だけが入力方法とは限らず、「タッチか、マウスとキーボードか」で分けたリスナーはサイトをタッチ専用にしてしまう、という内容です。F98は、判定が真になる端末では、達成基準2.1.1「キーボード」も満たさないことが多いと述べています。
この判定が避けようとした待ち時間は、もうありません。Chromeでは2014年から、iOSのSafariでは2016年から、viewportのmetaタグで width=device-width を指定したページなら、タップの直後にクリックが送られます。
タッチ画面付きのノートパソコン、キーボードカバーを付けた2-in-1のタブレット、Bluetoothのキーボードやマウスをつないだスマートフォンやタブレットは、どれもタッチ画面とほかの入力方法を併せ持つため、影響はスマートフォンにとどまりません。
10グループ中3グループに影響
- 全盲 (影響あり)
- 弱視 (影響なし)
- 色覚 (影響なし)
- ろう (影響なし)
- 難聴 (影響なし)
- 発話 (影響なし)
- 手の操作 (影響あり)
- 筋力・可動域 (影響あり)
- 認知 (影響なし)
- 光過敏 (影響なし)
- 手の操作が限られる タッチ画面付きのノートパソコンやキーボードを付けたタブレットで、キーボード、スイッチ、音声操作を使う人は、Enterキーで押します。Enterキーはクリックとしてページに届くため、パネルは開きません。ChromeとEdgeでは、「絞り込みをクリック」という声も、マウスのイベントとクリックとして届くため、何も起きません。
- 筋力や可動域が限られる 手にふるえがある人や疲れやすい人は、作業の途中で、画面、マウスやトラックボール、キーボードを使い分けることがあります。ここでは、画面に手を伸ばすのがどれほどつらくても、指で触れるしかありません。
- 視覚を使わない タッチ画面付きのノートパソコンのChromeやEdgeでは、NVDAやJAWSなどのスクリーンリーダーでボタンを押すと、クリックとしてページに届き、touchendは届きません。そのため「絞り込み」は折りたたみと読まれたまま開きません。Firefoxはアクセシビリティの仕組みを通した押下にタッチのイベントも加えるため、Firefoxでは開きます。
ボタンには名前、役割、aria-expanded の状態があり、マークアップのチェックはすべて合格します。スキャンはタッチ画面のないデスクトップのブラウザーで動くため、判定は偽になり、ページは click を待ちます。スクリプトでのクリックもキー操作もすべて成功します。axeにはこれを調べるルールがありません。EaseWebの診断は、各ページをタッチ画面を模擬した状態でもう一度開き、コントロールを比べます。1回目には自身の click のリスナーがあり、2回目には touchend か touchstart のリスナーがあって click、pointerup、mouseup のリスナーがないコントロールと、1回目に表示され2回目に隠れているコントロールを、要確認として記録します。確定としないのは、クリックがページの上位の要素で処理されている場合があるためです。フレームワークがページのルートに付けるリスナーは見えません。このコードは、タップの待ち時間を扱った古い回答や解説に今も出てくるため、それを元に生成されたコードにも入り込むことがあります。
試してみる
マウスで「絞り込み」を開いてから、TabキーとEnterキーでも開いてみましょう
このデモは、タッチ画面付きのノートパソコンで動くChromeやEdgeと同じように、タッチ画面がある端末として動きます。タッチ画面があれば、「絞り込み」をタップしても試してください。
問題あり 修正できますか?
マグカップ 12件
修正方法
どの端末でもclickを待つ
<button type="button" class="filters-toggle" aria-expanded="false" aria-controls="filters"> 絞り込み</button><form id="filters" class="filters" hidden> …</form>問題点3点
- タッチ画面付きのノートパソコンやキーボードを付けたタブレットでは
'ontouchstart' in windowが真になり、ボタンはtouchendだけを待ちます。 - マウスのクリックでは
touchendが発生しないため、「絞り込み」をクリックしても何も起きません。 - EnterキーとSpaceキーはクリックでボタンを押すため、これらでも何も起きません。ChromeとEdgeでは、スクリーンリーダーと音声操作でも同じです。
<button type="button" class="filters-toggle" aria-expanded="false" aria-controls="filters"> 絞り込み</button><form id="filters" class="filters" hidden> …</form>修正の手順2ステップ
- タッチの判定を削除します。どの押し方を受け付けるかを、ページが決めることはなくなります。
- ボタン本来の
clickを待ちます。タップでは指を離したときに発生し、マウスのクリック、フォーカスしたボタンでのEnterキーとSpaceキー、スクリーンリーダー、音声操作でも発生します。どれを使ってもパネルが開き、いつでも持ち替えられます。
これで修正前の例は直り、2.5.6を満たします。ページに <meta name="viewport" content="width=device-width"> がある限り、タップの反応も遅くなりません。
この方法を選ぶ理由:まずHTMLの要素を使う
タッチイベントは、加えて使う分には問題ありません。写真の列を指でスワイプしたり、スライダーをドラッグしたりするために touchstart や touchmove を待ってもかまいません。ただし、同じことをするボタンを横に置いて click で動かし、どの端末でも表示しておきます。同じ間違いはCSSでも起きます。タッチならスワイプで足りると考えて、@media (pointer: coarse) や (hover: none) でボタンを隠すと、同じ端末のマウスとキーボードからは使えなくなります。pointer: coarse が表すのは主なポインターだけなので、キーボードとトラックパッドを付けたタブレットでも当てはまることがあります。
タップの速さを残そうと touchend と click の両方を待つと、touchend で preventDefault() を呼ばない限り、1回のタップで処理が2回実行されます。呼んだとしても、ボタンの上で始まったタッチがスクロールに変わると、押したことになる場合があります。touchend は、タッチが始まった要素で発生するからです。touchstart で実行すると、指を離す前に動いてしまいます。これは押した瞬間に実行され、キャンセルできないボタンで扱っています。pointerup も近道にはなりません。キーボードでは発生しないからです。使うのは click か、コンポーネントライブラリーの押下イベントのうち、離したときに発生し、キーボードでも発生するものです。ボタンを結び付けるコードには、isTouch や isMobile の判定を入れないようにします。
修正の確認
4項目
確認方法: タッチ、マウス、キーボード、音声入力、スクリーンリーダー
OS、ブラウザー、支援技術のバージョン、ビルド、日付と、各手順の実際の結果を記録してください。共通のボタンやメニューのスクリプトを変更したら、もう一度確認します。
制限
これは出発点となる実装例で、すべてのアプリケーションでの動作を保証するものではありません。ここで扱うのは、タッチの判定で選んだリスナーです。タッチ端末で矢印ボタンを隠したカルーセルは、スワイプが唯一の方法になります。これはボタンで代われないピンチ・ドラッグ・傾きのジェスチャーで扱っています。マウスを見つけるとホバーで開くメニューや、本物のキーボードの代わりにページが押し付ける画面上のキーボードも、同じ達成基準を満たさないことがあり、別の確認が必要です。認められる制限もあります。タッチタイピングの練習ソフトはキーボードでの入力を求めてかまいません。それが教える内容そのものだからです。利用者が実際に使うタッチ画面付きのノートパソコンやタブレットで確認してください。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
参考資料
- WCAG Understanding: concurrent-input-mechanisms(新しいタブで開きます)
- WCAG Technique F98(新しいタブで開きます)
- w3c.github.io: touch-events(新しいタブで開きます)
- developer.chrome.com: 300ms-tap-delay-gone-away(新しいタブで開きます)
- developer.mozilla.org: click_event(新しいタブで開きます)
- source.chromium.org: ax_object.cc(新しいタブで開きます)
- searchfox.org: LocalAccessible.cpp(新しいタブで開きます)
- searchfox.org: StaticPrefList.yaml(新しいタブで開きます)
EaseWebのサービス
修正した問題を、次のリリースで再発させない
このガイドのような修正方法を、コーディングエージェントが従うルールと、CIのチェックに組み込みます。あわせて定期的に、キーボードとスクリーンリーダーで手動の再テストを行います。