本文へ移動
easeweb
ご相談
トピックを検索

ページではなくサブメニューが開いてしまうドロップダウンの親メニュー

1つのリンクがセクションのページへの移動とサブメニューの開閉を兼ねているため、Enterキーで何が起きるかをスクリプトが決めてしまい、一覧とページのどちらが開くかも伝わらない

WCAG 2.2
SC 2.1.1ASC 4.1.2A
必須とする規格
Section 508 · EN 301 549(EU) · JIS X 8341-3
問題あり event.preventDefault();
アクセシビリティの問題を示した図: 全盲:Enterで開くのは、一覧?ページ?
01

問題

キーボードの利用者はメニューのリンクで目的のページへ移動できるとは限らず、スクリーンリーダーの利用者にはEnterキーで一覧が開くのかページを離れるのかが分からない

02

試してみる

キーボードだけで「商品」のページへ移動し、次に「照明」へ移動してみましょう

  • 問題1: 「商品」でEnterキーを押します。一覧は開きますが、下の欄は「商品、リンク」と読むだけです。もう一度Enterキーを押すと、何の予告もなく「商品」のページへ移動します。

  • 問題2: 「商品」でEnterキーを押すと一覧が開いたり閉じたりするだけで、「商品」のページへは移動できません。マウスで「商品」をクリックすると、すぐに移動します。

  • 修正を適用します。 リンクでEnterキーを押せば必ずそのページへ移動し、一覧は開閉状態を伝えるボタンで開きます。

問題あり 修正できますか?

スクリーンリーダーの読み上げ:

(Tabでメニューへ移動)

再現デモです。「問題あり」は意図的にアクセシブルでない状態にしています。

03

修正方法

ページにはリンクを、一覧には専用のボタンを用意する

修正前

1回目で一覧が開き、2回目でリンク先へ移動する

<nav aria-label="メイン">  <ul class="menu">    <li>      <a href="/">ホーム</a>    </li>    <li class="has-sub">      <a href="/products">商品</a>      <ul>        <li>          <a href="/products/lamps">照明</a>        </li>        <li>          <a href="/products/chairs">椅子</a>        </li>        <li>          <a href="/products/rugs">ラグ</a>        </li>      </ul>    </li>    <li>      <a href="/about">会社概要</a>    </li>  </ul></nav>
問題点2点

マウスではポインターを重ねた時点で一覧が開くため、クリックすれば必ずリンク先へ移動します。リンクでEnterキーを押したときも同じclickイベントが発生するため、ここで問題になります。

  • 「商品」での1回目のEnterは取り消され、代わりに一覧が開きます。
  • 「商品」は押す前も後も「商品、リンク」と読まれるため、一覧が開いたことも、次のEnterでページを離れることも伝わりません。
修正後

リンクと、その横のボタン

<nav aria-label="メイン">  <ul class="menu">    <li>      <a href="/">ホーム</a>    </li>    <li class="has-sub">      <a href="/products">商品</a>      <button type="button" aria-expanded="false" aria-controls="sub-products" aria-label="商品のページ一覧">▾</button>      <ul id="sub-products" tabindex="-1" hidden>        <li>          <a href="/products/lamps">照明</a>        </li>        <li>          <a href="/products/chairs">椅子</a>        </li>        <li>          <a href="/products/rugs">ラグ</a>        </li>      </ul>    </li>    <li>      <a href="/about">会社概要</a>    </li>  </ul></nav>
修正の手順6ステップ
  1. 「商品」はハンドラーのないただのリンクに戻します。Enter、クリック、タップのどれでも、1回目で「商品」のページへ移動します。
  2. その直後に、シェブロンを描いたHTML標準のbuttonを置きます。Enter、Space、クリックで一覧を開閉できます。
  3. buttonには「商品のページ一覧」という名前を付け、スクリーンリーダーや音声操作でリンクと区別できるようにします。大きさは24×24ピクセル以上にします。
  4. buttonに hidden と連動する aria-expanded を付けます。「商品のページ一覧、ボタン、折りたたみ」、開くと「展開」と読み上げられます。aria-controls で一覧と結び付けます。
  5. Escapeで一覧を閉じてフォーカスをbuttonに戻し、フォーカスが項目から離れたら、フォーカスを動かさずに閉じます。
  6. 一覧に tabindex="-1" を付けます。一覧の中をクリックしてもフォーカスが項目の内側に残り、離れたとは見なされません。

これで二つの修正前の例はどちらも直り、2.1.1と4.1.2を満たします。各コントロールが一つの役目だけを持ち、それを伝えるからです。W3CのAPGにある、上段のリンクを残したナビゲーションの例(Disclosure Navigation Menu with Top-Level Links)と同じ形です。WordPressのナビゲーションブロックも、サブメニューをマウスを重ねて開く設定にし、矢印を表示していれば、この形で出力されます。

この方法を選ぶ理由:まずHTMLの要素を使う

混同しやすいもの
04

デザインの案

1つのメニュー項目でも、ページへの移動と一覧の表示を両立できる

「商品」の描き方を4通り並べました。マウスを使わずに、Tabキーでそれぞれを移動してみてください。言葉の上でEnterキーを押すとそのページへ、シェブロンや+の上で押すと一覧が開きます。3つはどちらもキーボードで使えます。最後の1つは、ポインターでしか一覧が開きません。

デザインファイルで

  • 「商品」という言葉を押したときの動作を、ページへの移動か一覧の表示か、どちらか1つに決める。
  • 言葉でページへ移動するなら、シェブロンや+は線か余白で区切り、別の押す場所として描く。
  • 言葉で一覧を開くなら、「商品」のページを一覧の先頭に、目に付くように入れる。
  • シェブロンには「商品のページ一覧」のような名前をデザインファイルに書き、隣のリンクと区別できるようにする。
  • 開いた状態も描き、シェブロンは上向きに、+は-にする。

合格

  • 線で2つに分けた1つのピル 「商品」とシェブロンを1つの枠線付きのピルに収め、1pxの線で区切ります。1つの項目に2つの端があるように見え、言葉はページへ、シェブロンは一覧を開いて上を向きます。左右はそれぞれのホバーで塗られ、フォーカスリングもそれぞれに付きます。文字は白地に#1a1a1a(17.40:1)です。
  • 先頭に「すべての商品」を置いたパネル 「商品」はパネルを開くだけにし、以前開いていたページは、パネルの先頭でいちばん大きなリンクにします。「すべての商品」と書いた色付きのカード(#f5f2ecに#1a1a1a、15.58:1)です。ヘッダーのTabの移動先は1つのままで、一覧ページへは1回押す操作が増えますが、見落とされない場所にあります。
  • スマートフォンのメニュー:行と、専用の+ スマートフォンのメニューでは、「商品」の行を2つに分けます。言葉はページへ移動し、右端の線で区切った正方形の+は、下に「照明」「椅子」「ラグ」を開いて-に変わります。言葉を1回押せば必ずページへ移動するため、どうなるかを推測する必要がありません。

不合格

05

修正の確認

5項目、マウス不要

確認方法: キーボード、スクリーンリーダー、タッチ、拡大表示

5件中0件を確認済み

OS、ブラウザーと支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。共通のヘッダーやメニューのコンポーネントを変更した際は、再度確認します。

スクリーンリーダーでの aria-expandedの読まれ方

制限

このガイドで扱うのは、リンクでありながらサブメニューも開く上段の項目です。スクリプトもボタンもなくマウスを重ねたときだけ開くサブメニューや、一覧が開いているかどうかを伝えないボタンは、マウスでしか開かないか、開閉が伝わらないドロップダウンメニューで扱っています。コマンドを並べるアプリケーションのメニューは、代わりにARIAのメニューパターンに従います。スクリプトは、アニメーション、マウスを重ねて開く操作、入れ子の階層を含まない最小限の例です。狭い画面のメニューも含めて、実際に使用する支援技術で操作全体を確認してください。

よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。

EaseWebのサービス

修正した問題を、次のリリースで再発させない

このガイドのような修正方法を、コーディングエージェントが従うルールと、CIのチェックに組み込みます。あわせて定期的に、キーボードとスクリーンリーダーで手動の再テストを行います。

サービス内容を見る