アクセシビリティを考えたドロップダウンメニューを実装する

多くのWebサイトに設置されているドロップダウンメニュー。うまくカテゴリー分けされていれば非常にわかりやすく、スペースも取らないので制作側からも愛されていますね。しかしアクセシビリティの観点から考えると、ちょっとやっかいな存在ではあります。マウスがうまく利用できないユーザーはキーボードを使ってページやリンクを移動しますが、ドロップダウンメニューは tab キーを使ってもサブメニューが表示されないのです。今回はこの問題を解決しようと思います!


tabキーで操作できるドロップダウンメニュー
こちらのGif画像のように、カーソルではなくキーボードの tab キーを使ってリンクを推移できるようにします。通常のHTMLとCSSを使った設置方法だと隠されている子メニューが表示されないので、キーボード操作でもうまく表示するのが今回の目標です。ちなみにこのブログのナビゲーションメニューにはすでに実装済みです!

まずは通常のドロップダウンメニューを作成

親メニューにマウスカーソルを合わせると、子メニューが表示される通常のドロップダウンメニューを作成します。

HTML

ul リストを入れ子にしてメニュー階層を実装。子メニューのあるリストには menu-item-has-children、子メニューには sub-menu というクラスをつけます。また、メニューを包む nav タグには role 属性で navigation を与え、その要素がナビゲーションであることを印づけます。

<nav role="navigation">
  <ul>
    <li class="menu-item-has-children">
      <a href="#">Coding ▼</a>
      <ul class="sub-menu">
        <li><a href="#">CSS</a></li>
        <li><a href="#">HTML5</a></li>
        <li><a href="#">WordPress</a></li>
        <li><a href="#">jQuery</a></li>
        <li><a href="#">SVG</a></li>
      </ul>
    </li>
    <li class="menu-item-has-children">
      <a href="#">Design ▼</a>
      <ul class="sub-menu">
        <li><a href="#">Web Design</a></li>
        <li><a href="#">Fonts</a></li>
        <li><a href="#">Colour</a></li>
      </ul>
    </li>
    <li><a href="#">Tips</a></li>
    <li><a href="#">For Beginner</a></li>
  </ul>
</nav>

role は日本語で「役割」を意味し、各要素がどんな役割を持つのかを定義できます。文書構造に印をつけ、アクセシビリティの向上を図りましょう。navigation 以外にも以下の役割が用意されています。

  • application(アプリケーション)
  • banner(バナー・ヘッダー等)
  • complementary(補足・サイドバー等)
  • contentinfo(コンテンツ情報・フッター等)
  • main(メインコンテンツ)
  • search(検索機能)

各roleの詳しい説明は「レイアウトで使うランドマークのrole属性【アクセシビリティ】【WAI-ARIA】」という記事が参考になるので、一度目を通してみてください。

CSS

親メニュー部分は、float: left; で横並びにさせるだけです。

/* 親メニュー - Parent nav */
nav > ul > li {
  position: relative;
  float: left;
  margin-right: 45px;
}
nav a {
  color: #0bd;
  text-decoration: none;
}
nav ul a:hover {
  color: #0090aa;
}

で、子メニューの部分は position: absolute; で表示位置を指定した後、display: none; で隠しておきます。

/* 子メニュー - .sub-menu */
nav .sub-menu {
  position: absolute;
  width: 180px;
  background: #0bd;
  top: 30px;
  display: none;
}
nav .sub-menu a {
  color: #fff;
  padding: 10px 15px;
  display: block;
}
nav .sub-menu a:hover {
  color: #fff;
}

あとは親メニューにホバーした時に子メニューを display: block; で表示させればドロップダウンメニューの完成です。

/* ホバーで子メニュー表示 */
nav .menu-item-has-children:hover ul {
  display: block;
}
nav li.menu-item-has-children li a:hover {
  background: #0090aa;
}

こんな感じ。子メニューを含むメニューにカーソルをあわせると、子メニューが下に表示されます。よくあるドロップダウンメニューですね。

See the Pen Drop-Down Navigation Menu by Mana (@manabox) on CodePen.

Tabキーでフォーカスした時に子メニューを表示

nontab-dropdown
親メニューに tab でフォーカスを当てても、このままでは上記Gifのように親メニューのリンク移動しかできません。:focus 擬似クラスを用いても、フォーカスしている要素が親メニューから子メニューに移ると動作しなくなります。ということでおなじみjQueryでフォーカスしている要素にクラスを与えて、あれこれ操作できるようにしましょう。

JavaScript

親メニューである .menu-item-has-children a と、子メニューである .sub-menu a にフォーカスすると、子メニューを包む ul.sub-menu に新たに focused というクラスを付与します。

$(function() {
  $('.menu-item-has-children a').focus( function () {
    $(this).siblings('.sub-menu').addClass('focused');
  }).blur(function(){
    $(this).siblings('.sub-menu').removeClass('focused');
  });

// サブメニュー用
  $('.sub-menu a').focus( function () {
    $(this).parents('.sub-menu').addClass('focused');
  }).blur(function(){
    $(this).parents('.sub-menu').removeClass('focused');
  });
});

CSS

CSSではホバー時と同様、フォーカスされた時に display: block; で子メニューが表示されるようにします。

nav .menu-item-has-children:hover ul,
nav .menu-item-has-children ul.focused {
  display: block;
}
nav li.menu-item-has-children li a:hover,
nav li.menu-item-has-children li a:focus {
  background: #0090aa;
}

完成!

tab でメニュー操作できるはずです!サンプル枠内の余白部分をクリックしてフォーカスがあたるようにした後、キー操作をお試しください!

See the Pen Accessible Drop-Down Navigation Menu by Mana (@manabox) on CodePen.

safari-pref
ちなみにMacのSafari・Firefoxではデフォルト設定のままだと tab 操作でリンクの移動ができないみたいです。Safariの場合はSafariの環境設定→詳細で「Tabキーを押した時にWebページ上の各項目を強調表示」をチェックすれば利用できるようになります。

mac-pref
FirefoxはMacのシステム環境設定→キーボード→ショートカットの「フルキーボードアクセス」で「すべてのコントロール」を選択します。素敵な tab キーライフを!

jQueryプラグイン「Accessible Mega Menu」

demo1
デモダウンロード
アクセシビリティを考慮したナビゲーションを設置するためのjQueryプラグインもリリースされています。Accessible Mega MenuAdobeのアクセシビリティチームが開発した、メガメニュー設置用プラグイン。tab で親メニューを移動し、return で子メニューを表示。子メニュー内は矢印キーや tab 、メニュー名の頭文字入力で移動できます。

demo2
同じプラグインを使った別のデモページでは、上記デモより頭文字入力での移動(子ページ表示時に「F」を押すと「Faculty」メニューがフォーカスされる等)がわかりやすく表現されています。


メガメニューのように、メニューの数が多くなればなるほど構造が複雑になってしまいます。プラグインを使って簡単に実装できるのはありがたいですね!ナビゲーションメニューはWebページを操作する上で重要な要素のひとつ。様々な角度からより使いやすく、アクセスしやすいメニューの実装を考えていきたいです。

シェアする

コメント

  • たしかにこのようにすれば、タブで移動している場合にサブメニューのアイテムの存在が分かりますが、本当にそれが必要なのか、ちょっと疑問に感じます。
    タブだけで移動している場合、この実装の場合は最初から全てのサブメニューを表示しているのと変わらないことになります。たとえば、最後のメニュー・アイテムのサブメニューの、さらに最後のサブメニュー・アイテムが目的の場合、そこまでたどり着くためにはかなりの回数、タブキーを連打する必要が出てくるのではないでしょうか。
    必要なことは、今フォーカスがあるメニュー・アイテムにサブメニューがあるかどうかが明確に分かり、その上でサブメニューを表示するかどうかはユーザーが決められる、というのが望ましい状態だと思うのですがどうでしょうか?

  • 確かにtabキーを連打またはホールドして移動する必要がありますが、私が実際に病気の関係でマウスやトラックパッドを使えなかった時は、カーソルを動かすことができないので、時間がかかってもTabキー移動できるのが本当に便利だったんですね。その体験を元になるべくキーボード操作でWebページを閲覧できる工夫をしたいと思っています。
    あってもなくても困らない機能なら、とりあえずつけてみてテストし、改善していければと思います。

  • 「キーボードで操作ができる」というのはすごく重要なことです。
    しかし、そのために全てを表示しなければいけないとは思えないんですね。
    タブキーで目的の親メニューまで到達する→サブメニューがあることが分かる→エンターキーを押すとサブメニューが現れる
    そんな風になっているのが望ましいのでは、というのが私の前の投稿の意図です。
    で、 メニュー・アイテムの数にもよりますが、サブメニューを導入して整理したくなる程度の数がある場合、「あってもなくても困らない」というレベルを超えて、「操作に時間がかかって困る」ものになってしまうケースが多いのではないかという気がしています。

  • おそらく紹介しているjQueryプラグインを使えばメニュー名の頭文字入力で移動できたり、Enterキーでサブメニュー表示できたりと、ご希望の動作に近いものが実装できると思います。ぜひ試してみてください!
    このサイトでもメニュー数の増減やテスト結果により設置を考えています。

ニュースレター

Web制作の最新情報やWebクリエイターボックスからのお知らせ、中の人の近況等を定期的にお送りいたします。 ぜひご登録ください!もちろん無料です! :)