このチュートリアルでは、ウェブサイトでアクセス可能なメイン ナビゲーションを作成する方法について説明します。セマンティック HTML、アクセシビリティ、ARIA 属性の使用がメリットよりもデメリットを生む場合があることについて学びます。
ウェブサイトのメイン ナビゲーションを構築するには、スタイル、機能、基盤となるマークアップやセマンティック情報など、さまざまな方法があります。実装が最小限で済みすぎると、ほとんどのユーザーにとってうまくいきますが、ユーザー エクスペリエンス(UX)は良くない場合があります。 過剰に設計されていると、ユーザーの混乱を招いたり、まったくアクセスできなくなったりする可能性があります。
ほとんどのウェブサイトでは、シンプルすぎず、複雑すぎないものを構築したいと考えています。
レイヤごとにレイヤを構築する
このチュートリアルでは、基本的な設定から始めて、ほとんどのユーザーが満足するのに十分な情報、スタイル、機能が提供されるまで、レイヤごとに対象物を追加します。そのためには、漸進的な拡張の原則を使用します。この原則では、最も基本的な堅牢なソリューションから始めて、段階的に機能レイヤを追加することが規定されています。なんらかの理由で 1 つのレイヤが機能しない場合でも、その下にあるレイヤに適切にフォールバックするため、ナビゲーションは機能します。
基本構造
基本的なナビゲーションには、<a>
要素と、リンクのデフォルトのスタイルとレイアウトを改善するための数行の CSS の 2 つが必要です。
<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);
}
これは、サイトへのアクセス方法に関係なく、ほとんどのユーザーにとってうまく機能します。このナビゲーションはマウス、キーボード、タッチデバイス、スクリーン リーダーを使用して利用できますが、改善の余地があります。この基本的なパターンに機能や情報を追加して拡張することで、エクスペリエンスを強化できます。
それには次のように対処します。
- アクティブなページをハイライト表示します。
- スクリーン リーダーのユーザーにアイテムの数をアナウンスします。
- ランドマークを追加し、スクリーン リーダーのユーザーがショートカットを使用してナビゲーションに直接アクセスできるようにします。
- 狭いビューポートでナビゲーションを非表示にします。
- フォーカスのスタイル設定を改善。
アクティブなページをハイライト表示する
アクティブなページをハイライト表示するには、対応するリンクにクラスを追加します。
<a href="/about-us" class="active-page">About us</a>
この方法の問題は、アクティブなリンクの情報が視覚的に伝わることです。目の見えないスクリーン リーダーのユーザーが、アクティブなページと他のページを見分けることができませんでした。幸い、Accessible Rich Internet Applications(ARIA)標準では、この情報を意味的に伝達する方法を提供しています。クラスの代わりに aria-current="page" 属性と値を使用します。
<ph type="x-smartling-placeholder"></ph>
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);
}
アイテム数をアナウンスする
目の見えないユーザーはナビゲーションを見ると、リンクが 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>
ランドマークを追加する
ほんの少しの労力で、スクリーン リーダーのユーザーにとって大きな改善が見られました。では、もう 1 つできることが残っています。ナビゲーションは意味的にはリンクのリストにすぎず、この特定のリストがウェブサイトのメインのナビゲーションであることを見分けるのは困難です。この通常のリストをナビゲーション リストに変えるには、<ul>
を <nav>
要素でラップします。
<nav>
要素の使用には、いくつかの利点があります。特に、スクリーン リーダーは、ユーザーが操作すると「ナビゲーション」のようなものをアナウンスし、ページにランドマークを追加します。ランドマークは、スクリーン リーダーがジャンプできる <header>
、<footer>
、<main>
などのページ上の特別な領域です。ページにランドマークを追加すると便利です。スクリーン リーダーのユーザーは、ページの他の部分を操作することなく、ページ上の重要な領域に直接アクセスできます。たとえば、NVDA で D キーを押すと、ランドマークからランドマークにジャンプできます。ナレーションでは、ローターを使用して VO+U キーを押すことで、ページ上のすべてのランドマークを一覧表示できます。
このリストには 4 つのランドマークがあります。banner(<header>
要素)、navigation(ナビゲーション)は <nav>
、main は <main>
要素、content information(コンテンツ情報)は <footer>
です。このリストは長くなりすぎないようにして、サイト内検索、ローカル ナビゲーション、ページネーションなど、UI の重要な部分のみをランドマークとしてマークすることをおすすめします。
サイト全体のナビゲーション、ページのローカル ナビゲーション、1 つのページにページ設定がある場合は、<nav>
要素を 3 つ配置することもできます。問題ありませんが、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>
簡潔なラベルで十分です。冗長になりすぎないようにします。「Navigation」などの式は省略するまたは「menu」この情報はスクリーン リーダーによってすでにユーザーに提供されているためです。
<ph type="x-smartling-placeholder">狭いビューポートでナビゲーションを非表示にする
個人的には、狭いビューポートでメイン ナビゲーションを非表示にするのはあまり好きではありませんが、リンクのリストが長くなりすぎると、それを回避する方法はありません。その場合、ユーザーにはリストではなく [メニュー] ボタンが表示されます。ハンバーガーのアイコンやその組み合わせですこのボタンをクリックすると、リストの表示と非表示が切り替わります。基本的な 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>
aria-expanded
属性は、ボタン コントロールの要素が展開されているかどうかをスクリーン リーダー ソフトウェアに伝えます。aria-label
は、ボタンにいわゆるユーザー補助機能用の名前(ハンバーガー アイコンの代替テキスト)を付与します。<svg>
にはaria-label
から提供されるテキストラベルがすでにあるため、aria-hidden
を使用する支援技術に表示されないようにします。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);
- ユーザーがいつでも(Esc キーを押すなどして)ナビゲーションを閉じることができると便利です。
- ボタンはナビゲーションの最初の要素にする必要があるため、
appendChild
ではなくinsertBefore
を使用することが重要です。キーボードまたはスクリーン リーダーのユーザーがボタンをクリックした後に Tab キーを押すと、リストの最初の項目がフォーカスされるはずです。ボタンがリストより後にある場合は、一致しません。
次に、ボタンのデフォルトのスタイル設定をリセットし、狭いビューポートでのみ表示されることを確認します。
@media (min-width: 48em) {
nav {
--nav-button-display: none;
}
}
/* Reset button styling */
button {
all: unset;
display: var(--nav-button-display, flex);
}
リストを非表示にする
リストを非表示にする前に、ナビゲーションとリストの位置とスタイルを設定し、狭いビューポートに合わせてレイアウトを最適化し、大画面でも適切に表示されるようにします。
まず、ページの自然な流れから <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;
}
狭いビューポートでは、ナビゲーションは次のようになります。
<ph type="x-smartling-placeholder">このリストには明らかに 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
を使用すると、ファイルが視覚的に表示されなくなり、アクセスできなくなるため、すべてのユーザーで非表示になります。
リストをアニメーション化する
display: none;
ではなく visibility: hidden;
を使用する理由としては、可視性をアニメーション化できる点が挙げられます。hidden
と visible
の 2 つの状態しかありませんが、transform
や opacity
などの別のプロパティと組み合わせて、スライド効果またはフェードイン効果を作成できます。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);
}
こうすると、モーションの縮小を望まない人だけにアニメーションが表示されるようになります。
フォーカスのスタイル設定を改善する
キーボード ユーザーは、ページの向きやナビゲーションに要素のフォーカス スタイルを使用します。デフォルトのフォーカス スタイルは、フォーカス スタイルがない(outline: none
を設定した場合に)より優れていますが、カスタム フォーカス スタイルをより明確に表示すると、ユーザー エクスペリエンスが向上します。
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
のブラウザ サポート
対応ブラウザ
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
フォーカスされている項目をハイライト表示する方法はいくつかあります。outline
プロパティは、border
で発生する可能性のあるレイアウトの不具合がなく、Windows の高コントラスト モードでも適切に動作するため、使用することをおすすめします。適切に動作しないプロパティは background-color
または box-shadow
です。カスタムのコントラスト設定ではまったく表示されない可能性があるためです。
これで、意味的にリッチで、アクセスしやすく、モバイル フレンドリーなメイン ナビゲーションが段階的に強化されました。
次のような改善が可能な点は常にあります。
- ナビゲーション内にフォーカスをトラップするか、狭いビューポートでページの残りの部分を非表示にすることもできます。
- ページの上部にスキップリンクを追加して、キーボード ユーザーがナビゲーションをスキップできるようにすることができます。
この記事の始まりを覚えている方は、解決策が「単純すぎず、複雑すぎない」ことを目指して始まりました。それは今のところなのです。ただし、ナビゲーションをオーバー エンジニアリングする場合があります。
ナビゲーションとメニュー
ナビゲーションとメニューには明確な違いがあります。Navigations は、関連ドキュメント間を移動するためのリンクのコレクションです。メニューは、ドキュメントで実行する操作の集合です。場合によっては、これらのタスクが重複することもあります。ナビゲーションには、モーダル ウィンドウを開くなどのアクションを実行するボタンも含めることも、ヘルプページなど、あるアクションが別のページに移動するメニューもあります。その場合は、ARIA ロールをマッシュアップするのではなく、コンポーネントの主な目的を特定し、それに応じてマークアップとロールを選択することが重要です。
<nav>
要素には暗黙的なナビゲーションの ARIA ロールが割り当てられており、これがナビゲーションであることを伝えるのに十分ですが、サイトでメニュー、メニューバー、メニュー項目も使用することがよくあります。Google ではこの 2 つの用語を同じ意味で使うことがあるため、2 つを組み合わせてスクリーン リーダーのユーザー エクスペリエンスを向上させるのも理にかなっています。通常そのようなことがない理由を知る前に、これらの役割の公式な定義を見てみましょう。
ナビゲーション ロール
ドキュメントや関連ドキュメントを移動するためのナビゲーション要素(通常はリンク)のコレクション。
ナビゲーション(ロール)WAI-ARIA 1.1
メニューの役割
メニューは通常、ユーザーが呼び出せる一般的なアクションまたは機能のリストです。メニューのロールは、メニュー項目のリストがデスクトップ アプリケーションのメニューと同じように表示される場合に適しています。
メニュー(ロール)WAI-ARIA 1.1
メニューバーのロール
メニューの表示形式。通常は横方向に表示されて表示されます。 メニューバー ロールは、Windows、Mac、Gnome デスクトップ アプリケーションのメニューバーと同様のメニューバーを作成するために使用されます。メニューバーは、よく使用するコマンドのセットを作成するために使用します。メニューバーのインタラクションが、デスクトップのグラフィカル ユーザー インターフェースにおける一般的なメニューバーのインタラクションと類似していることを確認することが推奨されています。
メニューバー(ロール)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 構造が必要です。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)やウェブアプリも含まれます。基盤となるスタックは関係ありません。デスクトップ アプリケーションと非常に近いものを構築する場合を除き、メニューのロールは使わないようにします。
参考情報
- Scott O'hara、Fixing Lists。
- Don't Use ARIA Menu Roles for Site Nav(Adrian Roselli 著)
- メニューとMenu Buttons(Heydon Pickering)
- 「WAI-ARIA メニューと、それらを慎重に扱うべき理由」(Marco Zehe)著。
- 責任を持ってコンテンツを非表示にする(Kitty Giraudel)。
- :focus-visible Is Here(Matthias Ott)
ヒーロー画像提供: Mick Haupt