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

このチュートリアルでは、ウェブサイトのユーザー補助対応のメイン ナビゲーションを構築する方法について説明します。セマンティック 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 キーを押すと、ランドマーク間を移動できます。VoiceOver では、VO+U キーを押してローターを使用して、ページ上のすべてのランドマークを一覧表示できます。

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

このリストには、4 つのランドマークがあります。バナー<header> 要素)、ナビゲーション<nav>)、メイン<main> 要素)、コンテンツ情報<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」、「mainnavigation」、「main」、「pagenavigation」、「select page ナビゲーション」、「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. 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 などのプロパティ宣言を使用することが重要です。これらのプロパティにより、ナビゲーションが非表示のときはリンクがフォーカス不可能になります。opacitytranslate を使用すると、コンテンツが視覚的に削除されるため、リンクは非表示になりますが、キーボードを使用してもアクセスできます。これは、混乱を招き、イライラします。visibility または display を使用すると、視覚的に非表示になり、アクセスできなくなります。そのため、すべてのユーザーに対して非表示になります。

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

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

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

次の 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 でリンクのデフォルトのフォーカス スタイルは次のようになります。

Chrome 103 でフォーカスされたリンクの周囲に青色の 2 ピクセルの枠線が表示されている。

独自の色で独自のスタイルを指定すると、この問題を改善できます。: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 のブラウザ サポート

対応ブラウザ

  • Chrome: 86。
  • Edge: 86.
  • Firefox: 85.
  • Safari: 15.4。

ソース

内側にスペースを設けた、はっきりと見える 2 ピクセルの暗い輪郭。

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

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

これで、意味的に豊かで、アクセスに優れ、モバイル対応のメイン ナビゲーションを段階的に強化しました。

改善の余地は常にあります。たとえば、次のような点が挙げられます。

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

この記事の冒頭で、ソリューションは「シンプルすぎず、複雑すぎない」ものを目指すと述べましたが、ここまででその目標を達成できたと思います。ただし、ナビゲーションをオーバー エンジニアリングする場合があります。

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

<nav> 要素には、要素がナビゲーションであることを伝えるのに十分な、暗黙的な ARIA ロール「navigation」が設定されていますが、多くのサイトでは、menu、menubar、menuitem も使用されています。これらの用語は、互換性がある場合があるため、組み合わせてスクリーン リーダー ユーザーの操作性を向上させることは理にかなっています。通常そのようなことがない理由を知る前に、これらの役割の公式な定義を見てみましょう。

ナビゲーション ロール

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

navigation(ロール)WAI-ARIA 1.1

メニューロール

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

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

メニューバーのロール

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

menubar(ロール)WAI-ARIA 1.1

menuitem ロール

メニューまたはメニューバーに含まれる選択肢の 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 作成方法ガイド(APG)に基づき、以下が含まれます。

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

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

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

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

参考情報

ヒーロー画像: Mick Haupt