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

このチュートリアルでは、ウェブサイトのアクセスしやすいメイン ナビゲーションを構築する方法について説明します。セマンティック HTML、ユーザー補助、ARIA 属性の使用が逆効果になる場合があることについて学びます。

Manuel Matuzović
Manuel Matuzović

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

ほとんどのウェブサイトでは、シンプルすぎず、複雑すぎないものを作成する必要があります。

レイヤごとに構築する

このチュートリアルでは、基本的な設定から始めて、ほとんどのユーザーに満足してもらえるだけの情報、スタイル、機能を提供するまで、レイヤごとに機能を追加していきます。これを実現するには、プログレッシブ エンハンスメントの原則を利用します。この原則では、最も基本的で堅牢なソリューションから始めて、機能のレイヤを段階的に追加していきます。なんらかの理由で 1 つのレイヤが機能しなくなっても、ナビゲーションは下位のレイヤに適切にフォールバックするため、引き続き機能します。

基本構造

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

  • HTML

    <a href="/home">Home</a>
    <a href="/about-us">About us</a>
    <a href="/pricing">Pricing</a>
    <a href="/contact">Contact</a>
    
  • CSS

    /* 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 つのランドマークが表示されます。banner は <header> 要素、navigation は <nav>、main は <main> 要素、content information は <footer> です。このリストは長すぎないようにしてください。サイト内検索、ローカル ナビゲーション、ページネーションなど、UI の重要な部分のみをランドマークとしてマークします。

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

すべて「ナビゲーション」と表示されている 3 つのランドマークを示す画像。
VoiceOver のローターに、ラベルのない 3 つのナビゲーション ランドマークが表示されています。

これらを区別できるようにするには、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 で「バナー」、「メイン ナビゲーション」、「メイン」、「ページ ナビゲーション」、「ページ ナビゲーションを選択」、「コンテンツ情報」のランドマークがリスト表示されている。
ステップ 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);
}
CodePen のステップ 5: ハンバーガー ボタンを追加するをご覧ください。

リストを非表示にする

リストを非表示にする前に、ナビゲーションとリストの位置とスタイルを設定して、レイアウトが狭いビューポートに最適化され、大画面でも見栄えがよくなるようにします。
まず、ページの自然なフローから <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-color と box-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: 0 や translateX(100%) ではなく、visibility: hidden や display: none などのプロパティ宣言を使用することが重要です。これらのプロパティにより、ナビゲーションが非表示のときにリンクがフォーカスされないようになります。opacity または translate を使用すると、コンテンツが視覚的に削除されるため、リンクは表示されなくなりますが、キーボードを使用してアクセスできるため、混乱や不満が生じる可能性があります。visibility または display を使用すると、視覚的に非表示になり、アクセスできなくなるため、すべてのユーザーに対して非表示になります。

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

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

display: none; ではなく visibility: hidden; を使用する理由は、表示 / 非表示をアニメーション化できるからです。hidden と visible の 2 つの状態しかありませんが、transform や opacity などの別のプロパティと組み合わせることで、スライドインやフェードインの効果を作成できます。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 のブラウザ サポート

Browser Support

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

Source

内側にスペースがある、はっきりと見える 2 ピクセルの暗いアウトライン。

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

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

おめでとうございます!プログレッシブ エンハンスメント、セマンティックな充実、アクセシビリティ、モバイル フレンドリーを考慮したメイン ナビゲーションを作成しました。

たとえば、次のような改善の余地が常にあります。

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

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

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

<nav> 要素には、ナビゲーションの暗黙的な ARIA ロールがあります。これは、要素がナビゲーションであることを伝えるのに十分ですが、サイトで menu、menubar、menuitem も使用されていることがよくあります。これらの用語は同じ意味で使用されることもあるため、スクリーン リーダー ユーザーのエクスペリエンスを向上させるために、これらを組み合わせることは理にかなっているように思えるかもしれません。通常はそうではない理由を学ぶ前に、これらのロールの公式な定義を見てみましょう。

ナビゲーション ロール

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

navigation(ロール)WAI-ARIA 1.1

メニューロール

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

menu(ロール)WAI-ARIA 1.1

menubar ロール

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

menubar(ロール)WAI-ARIA 1.1

menuitem ロール

menu または menubar に含まれる選択肢のセット内のオプション。

menuitem(ロール)WAI-ARIA 1.1

仕様は非常に明確です。ドキュメントまたは関連ドキュメントのナビゲーションには navigation を使用し、デスクトップ アプリケーションのメニューと同様のアクションまたは機能のリストには menu のみを使用します。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 構造が必要です。menuitem は menu の直接の子アイテムである必要があります。次のコードは、セマンティック動作を中断する可能性があります。

 <!-- 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)やウェブアプリも含まれます。基盤となるスタックは関係ありません。デスクトップ アプリケーションに非常に近いものを構築する場合を除き、メニューロールは避けてください。

参考情報