ウェブサイトのメイン ナビゲーションを作成する

このチュートリアルでは、ウェブサイトのアクセス可能なメイン ナビゲーションを作成する方法について説明します。セマンティック HTML とユーザー補助について、また ARIA 属性の使用がメリットよりむしろ有害となる場合があることについて学びます。

Manuel Matuzović
Manuel Matuzović

ウェブサイトのメイン ナビゲーションを構築するには、スタイル、機能、基盤となるマークアップ、セマンティック情報など、さまざまな方法があります。実装がミニマルすぎると、ほとんどのユーザーにとって問題なく機能しますが、ユーザー エクスペリエンス(UX)は良くない場合があります。 過度に設計されていると、ユーザーを混乱させたり、まったくアクセスできなかったりする可能性があります。

ほとんどのウェブサイトでは、シンプルすぎず、複雑すぎず、

レイヤごとに建物を構築する

このチュートリアルでは、まず基本的な設定を行い、大半のユーザーを満足させるのに十分な情報、スタイル設定、機能を提供できるレベルまで、対象物レイヤをレイヤごとに追加します。これを実現するには、プログレッシブ エンハンスメントの原則を利用します。この原則は、最も基本的で堅牢なソリューションから始めて、段階的に機能レイヤを追加するというものです。なんらかの理由で 1 つのレイヤが機能しない場合でも、ナビゲーションは基盤となるレイヤに正常にフォールバックするため、引き続き機能します。

基本構造

基本的なナビゲーションには、<a> 要素と、リンクのデフォルトのスタイルとレイアウトを改善するための数行の CSS が必要です。

<a href="/home">Home</a>
<a href="/about-us">About us</a>
<a href="/pricing">Pricing</a>
<a href="/contact">Contact</a>
/* Define variables for your colors */
:root {
  --color-shades-dark: rgb(25, 25, 25);
}

/* Use the alternative box model
Details: <https://web.dev/learn/css/box-model/> */
*{
  box-sizing: border-box;
}

/* Basic font styling */
body {
  font-family: Segoe UI, system-ui, -apple-system, sans-serif;
  font-size: 1.6rem;
}

/* Link styling */
a {
  --text-color: var(--color-shades-dark);
  border-block-end: 3px solid var(--border-color, transparent);
  color: var(--text-color);
  display: inline-block;
  margin-block-end: 0.5rem; /* See note at the bottom of this chapter */
  margin-inline-end: 0.5rem;
  padding: 0.1rem;
  text-decoration: none;
}

/* Change the border-color on :hover and :focus */
a:where(:hover, :focus) {
  --border-color: var(--text-color);
}
CodePen のステップ 1: 基本的な HTML と CSS を確認します。

この方法は、サイトへのアクセス方法に関係なく、ほとんどのユーザーにとって有効です。マウス、キーボード、タッチデバイス、スクリーン リーダーでナビゲーションにアクセスできるが、改善の余地がある。この基本パターンに機能や情報を追加して拡張することで、エクスペリエンスを強化できます。

それには次のように対処します。

  • アクティブなページをハイライト表示します。
  • スクリーン リーダーのユーザーにアイテムの数を知らせる。
  • ランドマークを追加し、スクリーン リーダーのユーザーがショートカットを使用してナビゲーションに直接アクセスできるようにします。
  • 狭いビューポートではナビゲーションを非表示にします。
  • フォーカスのスタイル設定を改善。

アクティブなページをハイライト表示する

アクティブなページをハイライト表示するには、対応するリンクにクラスを追加します。

<a href="/about-us" class="active-page">About us</a>

このアプローチの問題は、どのリンクがアクティブであるかを純粋に視覚的に伝えることです。目の見えないスクリーン リーダーのユーザーは、アクティブなページと他のページを見分けることができませんでした。幸いなことに、Accessible Rich Internet Applications(ARIA)標準では、この情報を意味的に伝達する方法も提供されています。クラスではなく、aria-current="page" 属性と値を使用してください。

aria-current(状態)は、コンテナまたは関連要素のセット内の現在のアイテムを表す要素を示します。 一連のページ設定リンク内でリンクを示すために使用されるページトークン。リンクは現在表示されているページを表すように視覚的にスタイル設定されます。 [Accessible Rich Internet Applications(WAI-ARIA)1.1](https://www.w3.org/TR/wai-aria/#aria-current)

属性を追加することで、スクリーン リーダーは単に「リンク、会社概要」ではなく「現在のページ、リンク、会社概要」のように読み上げるようになりました。

<a href="/about-us" aria-current="page" class="active-page">About us</a>

便利な副作用として、この属性を使用して CSS でアクティブなリンクを選択できるため、active-page クラスが廃止されます。

<a href="/home">Home</a>
<a href="/about-us" aria-current="page">About us</a>
<a href="/pricing">Pricing</a>
<a href="/contact">Contact</a>
/* Change border-color and color for the active page */
[aria-current="page"] {
  --border-color: var(--color-highlight);
  --text-color: var(--color-highlight);
}
ステップ 2: CodePen でアクティブなページをハイライト表示する
をご覧ください。

アイテムの数を通知する

目の見えるユーザーは、ナビゲーションを見ると、リンクが 4 つしかないことがわかります。目の見えないスクリーン リーダーのユーザーは、この情報をすばやく取得できません。場合によっては、リンクのリスト全体をひととおり確認する必要があります。この例のようにリストが短い場合は問題にならないかもしれませんが、40 個のリンクが含まれていると、この作業が面倒になる可能性があります。ナビゲーションに多くのリンクが含まれていることをスクリーン リーダーのユーザーが事前に知っている場合は、サイト内検索など、より効率的な別のナビゲーション方法を使用することになるかもしれません。
アイテム数を前もって伝えるには、各リンクをリストアイテム(<li>)でラップし、順序なしリスト(<ul>)にネストすることをおすすめします。

<ul>
  <li>
     <a href="/home">Home</a>
  </li>
  <li>
    <a href="/about-us" aria-current="page">About us</a>
  </li>
  <li>
    <a href="/pricing">Pricing</a>
  </li>
  <li>
    <a href="/contact">Contact</a>
  </li>
</ul>

スクリーン リーダーのユーザーがリストを見つけると、ソフトウェアが「リスト 4 項目」のように読み上げます。

以下は、Windows でスクリーン リーダー NVDA を使用する場合のナビゲーションのデモです。

以前のようにスタイルを変更する必要があります。

/* Remove the default list styling and create a flexible layout for the list */
ul {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Basic link styling */
a {
  --text-color: var(--color-shades-dark);

  border-block-end: 3px solid var(--border-color, transparent);
  color: var(--text-color);
  padding: 0.1rem;
  text-decoration: none;
}

リストを使用すると、スクリーン リーダーのユーザーに次のような多くのメリットがあります。

  • ユーザーは、アイテムを操作する前に、アイテムの総数を取得できます。
  • ショートカットを使用してリストアイテム間を移動できます。
  • ショートカットを使用してリスト間を移動することがあります。
  • スクリーン リーダーは、現在のアイテムのインデックス(「リストアイテム、4 つのうち 2」など)を読み上げることができます。

さらに、CSS なしでページが表示されている場合、リストには単なるリンクの山ではなく、一貫したアイテムのグループとしてリンクが表示されます。

Safari の VoiceOver については注目すべき点として、list-style: none を設定すると、これらのメリットがすべて失われることです。これは意図的なものです。WebKit チームは、リストがリストのように見えない場合に、リスト セマンティクスを削除することにしました。ナビゲーションの複雑さによって、これが問題になる場合もあれば、問題にならない場合もあります。一方、ナビゲーションは引き続き使用可能で、Safari の VoiceOver にのみ影響します。Chrome または Firefox で VoiceOver を使用する場合は、NVDA などの他のスクリーン リーダーと同様に、アイテム数が読み上げられます。一方、セマンティック情報は、状況によっては非常に役立つことがあります。その判断を下すには、実際のスクリーン リーダー ユーザーでナビゲーションをテストし、フィードバックを得る必要があります。Safari の VoiceOver を他のすべてのスクリーン リーダーと同様に動作させる必要がある場合は、<ul> で ARIA リストのロールを明示的に設定することで、この問題を回避できます。これにより、リストのスタイルを削除する前の状態に戻ります。見た目は変わりません。

<ul role="list">
  <li>
     <a href="/home">Home</a>
  </li>
  ...
</ul>
ステップ 3: CodePen のアイテム数を通知するを確認する。

ランドマークを追加

スクリーン リーダーのユーザー エクスペリエンスが大幅に向上しましたが、改善の余地がもう 1 つあります。ナビゲーションは意味的にはリンクのリストにすぎません。そのリストがウェブサイトのメインのナビゲーションであると判断するのは難しいでしょう。この通常のリストをナビゲーション リストに変換するには、<ul><nav> 要素でラップします。

<nav> 要素の使用には、いくつかの利点があります。特に、スクリーン リーダーは、ユーザーが操作すると「ナビゲーション」などの音声をアナウンスし、ページにランドマークを追加します。ランドマークは、スクリーン リーダーがジャンプできるページ上の特別な領域(<header><footer><main> など)です。ページにランドマークを設定すると、スクリーン リーダーのユーザーがページの他の部分を操作することなく、ページ上の重要な領域に直接アクセスできるようになるため、便利です。たとえば、NVDA で D キーを押すと、ランドマークからランドマークに移動できます。ナレーションでは、VO+U キーを押すことで、ローターを使用してページ上のすべてのランドマークをリストできます。

4 つのランドマーク(バナー、ナビゲーション、メイン、コンテンツ情報)のリスト。
ページ上のすべてのランドマークを一覧表示する VoiceOver のローター。

このリストには 4 つのランドマークがあります。banner<header> 要素、navigation<nav>main<main> 要素、content information)は <footer> です。このリストはあまり長くしないでください。サイト内検索、ローカル ナビゲーション、ページネーションなど、UI の重要な部分のみをランドマークとしてマークする必要があります。

サイト全体のナビゲーション、ページのローカル ナビゲーション、1 つのページにページネーションがある場合は、3 つの <nav> 要素を使用することもあります。問題ありませんが、今度はナビゲーション ランドマークが 3 つあり、意味的にはすべて同じように見えます。ページの構造をよく理解していないと、これらを区別するのは困難です。

どれも「ナビゲーション」と書かれた 3 つのランドマークの画像。
ラベルのないナビゲーション ランドマークが 3 つ表示されている VoiceOver のローター。

識別可能にするには、aria-labelledby または aria-label を使用してラベルを付ける必要があります。

<nav aria-label="Main">
    <ul>
      <li>
         <a href="/home">Home</a>
      </li>
      ...
  </ul>
</nav>
...
<nav aria-label="Select page">
    <ul>
      <li>
         <a href="/page-1">1</a>
      </li>
      ...
    </ul>
</nav>

選択したラベルがページのどこかにすでに存在する場合は、代わりに aria-labelledby を使用し、id 属性を使用して既存のラベルを参照できます。

<nav aria-labelledby="pagination_heading">
  <h2 id="pagination_heading">Select a page</h2>
  <ul>
    <li>
       <a href="/page-1">1</a>
    </li>
    ...
  </ul>
</nav>

簡潔なラベルで十分です。長くなりすぎないようにしてください。「ナビゲーション」や「メニュー」などの式は、スクリーン リーダーによってすでにユーザーに提供されているため省略します。

ランドマーク
VoiceOver によるランドマークの「banner」、「main integration」、「main」、「pagenav」、「select pagenav」、「content information」のリストが表示されている。
ステップ 4: CodePen でランドマークを追加するをご覧ください。

狭いビューポートでナビゲーションを非表示にする

個人的には、狭いビューポートでメイン ナビゲーションを非表示にするのはあまり好きではありませんが、リンクのリストが長くなりすぎると、それを回避する方法がありません。その場合、リストの代わりに「メニュー」というボタン、ハンバーガー アイコン、またはそれらの組み合わせが表示されます。ボタンをクリックすると、リストの表示と非表示が切り替わります。基本的な JavaScript と CSS の知識があれば対応できますが、UX とアクセシビリティに関して注意すべき点がいくつかあります。

  • アクセスしやすい方法でリストを非表示にする必要があります。
  • ナビゲーションはキーボードでアクセスできる必要があります。
  • ナビゲーションは表示の有無を通知する必要があります。

ハンバーガー ボタンの追加

プログレッシブ エンハンスメントの原則に従っているので、JavaScript をオフにしてもナビゲーションが機能し、理にかなっていることを確認する必要があります。
まず、ナビゲーションに必要なのはハンバーガー ボタンです。テンプレート要素内の HTML で作成し、JavaScript でクローンを作成して、ナビゲーションに追加します。

ハンバーガー ボタンが表示されているページ。
結果: 狭いビューポートでは、ナビゲーションにリンクではなくハンバーガー ボタンが表示されます。
<nav id="mainnav">
  ...
</nav>

<template id="burger-template">
  <button type="button" aria-expanded="false" aria-label="Menu" aria-controls="mainnav">
    <svg width="24" height="24" aria-hidden="true">
      <path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z">
    </svg>
  </button>
</template>
  1. aria-expanded 属性は、ボタンでコントロールする要素が展開されているかどうかをスクリーン リーダー ソフトウェアに伝えます。
  2. aria-label は、ボタンにいわゆるユーザー補助機能用の名前(ハンバーガー アイコンのテキスト代替)を付与します。
  3. <svg> にはすでに aria-label が提供するテキストラベルがあるため、aria-hidden を使用して支援技術で <svg> を非表示にします。
  4. aria-controls は、ボタンで制御する要素(JAWS など)をサポートする支援技術を示します。
const nav = document.querySelector('#mainnav')
const list = nav.querySelector('ul');
const burgerClone = document.querySelector('#burger-template').content.cloneNode(true);
const button = burgerClone.querySelector('button');

// Toggle aria-expanded attribute
button.addEventListener('click', e => {
  // aria-expanded="true" signals that the menu is currently open
  const isOpen = button.getAttribute('aria-expanded') === "true"
  button.setAttribute('aria-expanded', !isOpen);
});

// Hide list on keydown Escape
nav.addEventListener('keyup', e => {
  if (e.code === 'Escape') {
    button.setAttribute('aria-expanded', false);
  }
});

// Add the button to the page
nav.insertBefore(burgerClone, list);
  1. Esc キーを押すなどして、ユーザーがいつでもナビゲーションを閉じることができると便利です。
  2. ボタンはナビゲーションの最初の要素にする必要があるため、appendChild ではなく insertBefore を使用することが重要です。キーボードまたはスクリーン リーダーのユーザーが、ボタンをクリックした後に Tab キーを押した場合、リストの最初の項目にフォーカスが移動することを期待します。ボタンがリストの後ろにある場合は、そうではありません。

次に、ボタンのデフォルトのスタイルをリセットして、狭いビューポートにのみ表示されるようにします。

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
  }
}

/* Reset button styling */
button {
  all: unset;
  display: var(--nav-button-display, flex);
}
ステップ 5: CodePen にハンバーガー ボタンを追加するを確認する。

リストを非表示にする

リストを非表示にする前に、ナビゲーションとリストの位置とスタイルを設定して、レイアウトが狭いビューポートに最適化され、大きな画面でも適切に表示されるようにします。
まず、ページの自然な流れから <nav> を削除して、ビューポートの上端隅に配置します。

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
    --nav-position: static;
  }
}

nav {
  position: var(--nav-position, fixed);
  inset-block-start: 1rem;
  inset-inline-end: 1rem;
}

次に、新しいカスタム プロパティ (—-nav-list-layout) を追加して、狭いビューポートのレイアウトを変更します。レイアウトはデフォルトでは列ですが、大画面では行に切り替わります。

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
    --nav-position: static;
  }

  ul {
    --nav-list-layout: row;
  }
}

ul {
  display: flex;
  flex-direction: var(--nav-list-layout, column);
  flex-wrap: wrap;
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

狭いビューポートでは、ナビゲーションは次のようになります。

ナビゲーション リストとハンバーガー ボタンが表示されているページ。
ハンバーガー ボタンとリストの両方がビューポートの上端に配置されます。

リストには CSS が必要です。これを上端の隅まで移動して画面全体を垂直方向に表示し、background-colorbox-shadow を適用します。

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
    --nav-position: static;
  }
  
  ul {
    --nav-list-layout: row;
    --nav-list-position: static;
    --nav-list-padding: 0;
    --nav-list-height: auto;
    --nav-list-width: 100%;
    --nav-list-shadow: none;
  }
}

ul {
  background: rgb(255, 255, 255);
  box-shadow: var(--nav-list-shadow, -5px 0 11px 0 rgb(0 0 0 / 0.2));
  display: flex;
  flex-direction: var(--nav-list-layout, column);
  flex-wrap: wrap;
  gap: 1rem;
  height: var(--nav-list-height, 100vh);
  list-style: none;
  margin: 0;
  padding: var(--nav-list-padding, 2rem);
  position: var(--nav-list-position, fixed);
  inset-block-start: 0; /* Logical property. Equivalent to top: 0; */
  inset-inline-end: 0; /* Logical property. Equivalent to right: 0; */
  width: var(--nav-list-width, min(22rem, 100vw));
}

button {
  all: unset;
  display: var(--nav-button-display, flex);
  position: relative;
  z-index: 1;
}

狭いビューポートでは、シンプルなリストというよりもサイドバーのようのリストは次のようになります。

ナビゲーション リストが開きます。

最後に、リストを非表示にします。ユーザーがボタンを 1 回クリックしたときにのみリストを表示し、再度クリックしたときに非表示にします。ナビゲーションを非表示にすると重要なランドマークも非表示にすることになるため、ナビゲーション全体ではなく、リストのみを非表示にすることが重要です。

先ほど、aria-expanded 属性の値を切り替えるために、ボタンにクリック イベントを追加しました。その情報を、CSS でリストの表示と非表示を切り替える条件として使用できます。

@media (min-width: 48em) {
  ul {
    --nav-list-visibility: visible;
  }
}

ul {
  visibility: var(--nav-list-visibility, visible);
}

/* Hide the list on narrow viewports, if it comes after an element with
   aria-expanded set to "false". */
[aria-expanded="false"] + ul {
  visibility: var(--nav-list-visibility, hidden);
}

リストを非表示にするには、opacity: 0translateX(100%) ではなく、visibility: hiddendisplay: none などのプロパティ宣言を使用することが重要です。これらのプロパティは、ナビゲーションが非表示のときにリンクがフォーカスされないようにします。opacity または translate を使用すると、コンテンツが視覚的に削除されるため、リンクは見えないのにキーボードでのアクセスも可能になり、混乱して不満を感じます。visibility または display を使用すると、視覚的に非表示になり、アクセスできなくなるため、すべてのユーザーに表示されなくなります。

ステップ 6: リストを非表示にするをご覧ください。

リストをアニメーション化する

display: none; ではなく visibility: hidden; を使用する理由として、可視性をアニメーション化できるからです。状態は hiddenvisible の 2 つだけですが、transformopacity などの別のプロパティと組み合わせて、スライド効果またはフェードイン効果を作成できます。この場合、display: none では機能しません。display プロパティはアニメーション化できないためです。

次の CSS は、opacity を遷移してフェードインとフェードアウトの効果を作成します。

ul {
  transition: opacity 0.6s linear, visibility 0.3s linear;
  visibility: var(--nav-list-visibility, visible);
}

[aria-expanded="false"] + ul {
  opacity: 0;
  visibility: var(--nav-list-visibility, hidden);
}

代わりにモーションをアニメーション化する場合は、transition プロパティを prefers-reduced-motion メディアクエリでラップすることを検討してください。一部のユーザーはアニメーションによって吐き気、めまい、頭痛を引き起こす可能性があるためです。

ul {
  visibility: var(--nav-list-visibility, visible);
}

@media (prefers-reduced-motion: no-preference) {
  ul {
    transition: transform 0.6s cubic-bezier(.68,-0.55,.27,1.55), visibility 0.3s linear;
  }
}

[aria-expanded="false"] + ul {
  transform: var(--nav-list-transform, translateX(100%));
  visibility: var(--nav-list-visibility, hidden);
}

これにより、動きの軽減を好まない人にのみアニメーションが表示されるようになります。

ステップ 7: CodePen でリストをアニメーション化するを確認する。

フォーカスのスタイル設定を改善

キーボード ユーザーは、ページの向きとナビゲーションについては、要素のフォーカス スタイルに依存します。デフォルトのフォーカス スタイルは、フォーカス スタイルなし(outline: none を設定した場合に発生する)よりも優れていますが、カスタム フォーカス スタイルをわかりやすくすると、ユーザー エクスペリエンスが向上します。

Chrome 103 では、リンクのデフォルトのフォーカス スタイルは次のようになります。

フォーカスされているリンクを囲む青色の 2 ピクセルの枠線(Chrome 103)。

独自の色で独自のスタイルを指定することで、この数値を改善できます。:focus ではなく :focus-visible を使用すると、フォーカス スタイルを表示するのに適したタイミングをブラウザが判断できるようになります。:focus のスタイルは、マウス、キーボード、タッチ操作が必要かどうかにかかわらず、すべてのユーザーに表示されます。:focus-visible では、ブラウザは内部ヒューリスティックを使用して、キーボード ユーザーのみに表示するか、すべてのユーザーに表示するかを決定します。

/* Remove the default :focus outline */
*:focus {
  outline: none;
}

/* Show a custom outline on :focus-visible */
*:focus-visible {
  outline: 2px solid var(--color-shades-dark);
  outline-offset: 4px;
}

:focus-visible のブラウザ サポート

対応ブラウザ

  • 86
  • 86
  • 85
  • 15.4

ソース

枠線が 2 ピクセルで暗く、内側に余白がはっきりと表示される。

フォーカスされているアイテムをハイライト表示する方法はいくつかあります。border で発生する可能性があるレイアウトの破損はなく、Windows の高コントラスト モードでも適切に動作するため、outline プロパティの使用をおすすめします。適切に動作しないプロパティは、カスタム コントラスト設定ではまったく表示されない可能性があるため、background-color または box-shadow です。

暗い背景でフォーカスが紫色で強調表示されたサイト。
ステップ 8: CodePen でフォーカスのスタイルを改善するをご覧ください。

これで完了です。セマンティックで利用しやすく、アクセスしやすい、モバイル フレンドリーなメイン ナビゲーションが段階的に強化されています。

次のように、常に改善できることがあります。

  • ナビゲーション内にフォーカスをトラップするか、狭いビューポートでページの残りの部分を不活性にすることを検討してください。
  • ページの上部にスキップリンクを追加すると、キーボード ユーザーがナビゲーションをスキップできるようになります。

この記事が始まった経緯を覚えているなら、このソリューションは「シンプルすぎたり複雑すぎたりしない」ことを目的としており、今のところ、その答えが見つかります。ただし、ナビゲーションを過度に設計することは可能です。

ナビゲーションとメニューには明らかな違いがあります。ナビゲーションとは、関連ドキュメントに移動するためのリンクのコレクションです。メニューは、ドキュメントで実行するアクションのコレクションです。これらのタスクが重複することがあります。モーダル ウィンドウを開くなどのアクションを実行するボタンも組み込まれたナビゲーションや、あるアクションで別のページ(ヘルプページなど)に移動するメニューがあるとします。その場合は、ARIA ロールをマッシュアップするのではなく、コンポーネントの主な目的を特定し、それに応じてマークアップとロールを選択することが重要です。

<nav> 要素には、ナビゲーションの暗黙的な ARIA ロールがあります。これは、要素がナビゲーションであることを伝えるのに十分ですが、メニュー、メニューバー、メニューアイテムも使用するサイトもよくあります。これらの用語は同じ意味で使われることがあるため、これらを組み合わせてスクリーン リーダーのユーザー エクスペリエンスを向上させることも理にかなっていると考えられます。なぜそのようなことがよくあるのかを説明する前に、これらの役割の正式な定義を見てみましょう。

ナビゲーション ロール

ドキュメントや関連ドキュメントを移動するためのナビゲーション要素(通常はリンク)のコレクション。

ナビゲーション(ロール)WAI-ARIA 1.1

メニューロール

多くの場合、メニューはユーザーが呼び出せる一般的なアクションや機能のリストです。メニューのロールは、メニュー項目のリストがデスクトップ アプリケーションのメニューと同様の方法で表示される場合に適しています。

メニュー(ロール)WAI-ARIA 1.1

メニューバーのロール

通常はそのまま横向きに表示されるメニュー。メニューバー ロールは、Windows、Mac、Gnome デスクトップ アプリケーションのメニューバーと同様のメニューバーを作成するために使用します。メニューバーを使用すると、よく使用するコマンドの一貫したセットを作成できます。作成者は、メニューバーの操作が、パソコンのグラフィカル ユーザー インターフェースにおける一般的なメニューバーの操作と類似していることを確認する必要があります。

menubar(ロール)WAI-ARIA 1.1

メニュー項目のロール

メニューまたはメニューバーに表示される選択肢のセットのオプション。

menuitem(ロール)WAI-ARIA 1.1

ここでは仕様が非常に明確です。ドキュメントまたは関連ドキュメントとメニューの移動にナビゲーションを使用するのは、デスクトップ アプリケーションのメニューに類似したアクションや機能のリストのみです。今後 Google ドキュメントを作成しない場合、メイン ナビゲーションのメニューのロールはおそらく必要ありません。

どのようなメニューが適しているか

メニュー項目の主な用途はナビゲーションではなく、アクションを実行することです。データのリストまたは表があり、ユーザーがリスト内の各アイテムに対して特定の操作を行える場合を考えてみましょう。各行にボタンを追加して、ユーザーがボタンをクリックしたときのアクションを表示できます。

<ul>
  <li>
    Product 1

    <button aria-expanded="false" aria-controls="options1">Edit</button>

    <div role="menu" id="options1">
      <button role="menuitem">
        Duplicate
      </button>
      <button role="menuitem">
        Delete
      </button>
      <button role="menuitem">
        Disable
      </button>
    </div>
  </li>
  <li>
    Product 2
    ...
  </li>
</ul>

メニューロールを使用する場合の影響

失敗することが多いため、これらのメニューのロールは賢く使用することが重要です。

メニューには特定の DOM 構造が必要です。menuitemmenu の直接の子アイテムである必要があります。次のコードにより、セマンティック動作が損なわれる可能性があります。

 <!-- Wrong, don't do this -->
<ul role="menu">
  <li>
    <a href="#" role="menuitem">Item 1</a>
  </li>
</ul>

使い慣れているユーザーは、特定のキーボード ショートカットをメニューやメニューバーでも操作できることを期待しています。ARIA Authoring Practices Guide(APG)に基づいて、これには以下が含まれます。

  • メニュー項目を選択するには、Enter キーと Space キーを押します。
  • 矢印キーで上下左右のアイテム間を移動します。
  • Home キーまたは End キー: それぞれ最初または最後のアイテムにフォーカスを移動します。
  • A ~ Z キー: 入力した文字で始まるラベルを持つ次のメニュー項目にフォーカスを移動します。
  • Esc キーを押してメニューを閉じます。

スクリーン リーダーがメニューを検出すると、ソフトウェアによって自動的にブラウジング モードが変更され、前述のショートカットを使用できるようになります。スクリーン リーダーの使用経験が浅いユーザーは、ショートカットや使用方法を知らないため、メニューを使用できない可能性があります。

これは、Shift キーと Shift+Tab キーを使用できることを想定しているキーボード ユーザーの場合も同じです。

メニューやメニューバーを作成する際は、最初にそれらを使用することが適切かどうかなど、考慮すべきことがたくさんあります。一般的なウェブサイトを構築する場合は、リストとリンクを含む nav 要素があれば十分です。これには、シングルページ アプリケーション(SPA)やウェブアプリも含まれます。基盤となるスタックは重要ではありません。デスクトップ アプリケーションに非常に近いものを構築する場合を除き、メニューのロールは避けます。

参考情報

ヒーロー画像 by Mick Haupt