Questo tutorial descrive come creare una navigazione principale accessibile di un sito web. Scoprirai l'HTML semantico, l'accessibilità e come l'utilizzo degli attributi ARIA a volte possa fare più male che bene.
Esistono molti modi diversi per creare la navigazione principale di un sito web, in termini di stile, funzionalità, markup sottostante e informazioni semantiche. Se l'implementazione è troppo minimalista, funziona per la maggior parte delle persone, ma l'esperienza utente (UX) potrebbe non essere ottimale. Se è troppo complessa, potrebbe confondere gli utenti o addirittura impedire loro di accedervi.
Per la maggior parte dei siti web, è consigliabile creare un sito che non sia né troppo semplice né troppo complicato.
Costruzione strato per strato
In questo tutorial inizierai con una configurazione di base e aggiungerai livelli degli elementi livello per livello fino a fornire informazioni, stile e funzionalità sufficienti per soddisfare la maggior parte degli utenti. Per farlo, utilizza il principio del potenziamento progressivo, che prevede di iniziare con la soluzione più semplice e solida e di aggiungere progressivamente livelli di funzionalità. Se un livello non funziona per qualche motivo, la navigazione continuerà a funzionare perché eseguirà il graceful fallback al livello sottostante.
Struttura di base
Per una navigazione di base, hai bisogno di due cose: elementi <a> e alcune righe di CSS per migliorare lo stile e il layout predefiniti dei link.
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); }
Questo metodo funziona bene per la maggior parte degli utenti, indipendentemente dal modo in cui accedono al sito. La navigazione è accessibile con un mouse, una tastiera, un dispositivo touch o uno screen reader, ma c'è margine di miglioramento. Puoi migliorare l'esperienza estendendo questo pattern di base con funzionalità e informazioni aggiuntive.
Ecco quello che puoi fare:
- Evidenzia la pagina attiva.
- Annuncia il numero di elementi agli utenti dello screen reader.
- Aggiungi un punto di riferimento e consenti agli utenti di screen reader di accedere direttamente alla navigazione utilizzando una scorciatoia.
- Nascondi la navigazione nelle aree visibili strette.
- Migliora lo stile dello stato attivo.
Evidenzia la pagina attiva
Per evidenziare la pagina attiva, puoi aggiungere una classe al link corrispondente.
<a href="/about-us" class="active-page">About us</a>
Il problema di questo approccio è che trasmette l'informazione su quale link è attivo in modo puramente visivo. Un utente non vedente che utilizza uno screen reader non potrebbe distinguere la pagina attiva dalle altre pagine. Fortunatamente, lo standard Accessible Rich Internet Applications (ARIA) offre un modo per comunicare queste informazioni anche dal punto di vista semantico. Utilizza l'attributo e il valore aria-current="page" anziché una classe.
aria-current (stato) indica l'elemento che rappresenta l'elemento corrente all'interno di un contenitore o di un insieme di elementi correlati.
Un token di pagina utilizzato per indicare un link all'interno di un insieme di link di impaginazione, in cui lo stile del link è visivamente formattato per rappresentare la pagina attualmente visualizzata.
[Accessible Rich Internet Applications (WAI-ARIA) 1.1](https://www.w3.org/TR/wai-aria/#aria-current)
Con l'attributo aggiuntivo, uno screen reader ora annuncia qualcosa come "pagina corrente, link, Chi siamo" anziché solo "link, Chi siamo".
<a href="/about-us" aria-current="page" class="active-page">About us</a>
Un effetto collaterale positivo è che puoi utilizzare l'attributo per selezionare il link attivo in CSS, rendendo obsoleta la classe 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);
}
Annuncia il numero di elementi
Osservando la navigazione, gli utenti vedenti possono capire che contiene solo quattro link. Un utente non vedente che utilizza uno screen reader non può ottenere queste informazioni con la stessa rapidità. Potrebbero dover scorrere l'intero elenco di link. Questo potrebbe non essere un problema se l'elenco è breve come in questo esempio, ma se contiene 40 link, l'attività può essere complessa. Se un utente di screen reader sa in anticipo che la navigazione contiene molti link, potrebbe decidere di utilizzare un modo di navigazione diverso e più efficiente, come la ricerca sul sito.
Un buon modo per comunicare in anticipo il numero di elementi è inserire ogni link in un elemento di elenco (<li>), nidificato in un elenco non ordinato (<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>
Quando un utente di screen reader trova l'elenco, il software annuncerà qualcosa come "elenco, 4 elementi".
Ecco una demo della navigazione utilizzata con lo screen reader NVDA su Windows.
Ora devi adattare lo stile per renderlo simile a quello precedente.
/* 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;
}
L'utilizzo degli elenchi può offrire molti vantaggi agli utenti di screen reader:
- Possono ottenere il numero totale di elementi prima di interagire con questi.
- Potrebbero utilizzare le scorciatoie per passare da un elemento all'altro dell'elenco.
- Potrebbero utilizzare le scorciatoie per passare da un elenco all'altro.
- Lo screen reader potrebbe annunciare l'indice dell'elemento corrente (ad esempio, "elemento dell'elenco, due di quattro").
Inoltre, se la pagina viene presentata senza CSS, l'elenco mostra i link come un gruppo coerente di elementi anziché come un semplice insieme di link.
Un dettaglio importante di VoiceOver in Safari è che perdi tutti questi vantaggi quando imposti list-style: none. Si tratta di un comportamento previsto. Il team di WebKit ha deciso di rimuovere la semantica degli elenchi quando un elenco non sembra un elenco. A seconda della complessità della navigazione, questo potrebbe essere o meno un problema. Da un lato, la navigazione è ancora utilizzabile e influisce solo su VoiceOver in Safari. VoiceOver con Chrome o Firefox annuncia comunque il numero di elementi, così come altri screen reader, come NVDA. D'altra parte, le informazioni semantiche potrebbero essere molto utili in alcune situazioni. Per prendere questa decisione, devi testare la navigazione con utenti reali di screen reader e ricevere il loro feedback. Se decidi che VoiceOver in Safari deve comportarsi come tutti gli altri screen reader, puoi risolvere il problema impostando esplicitamente il ruolo dell'elenco ARIA su <ul>. In questo modo, il comportamento viene ripristinato allo stato precedente alla rimozione dello stile dell'elenco. Visivamente, l'elenco ha lo stesso aspetto.
<ul role="list">
<li>
<a href="/home">Home</a>
</li>
...
</ul>
Aggiungi un punto di riferimento
Con un piccolo sforzo, hai apportato grandi miglioramenti per gli utenti di screen reader, ma c'è un'altra cosa che puoi fare. Semanticamente, la navigazione è ancora solo un elenco di link ed è difficile capire che questo elenco specifico è la navigazione principale del tuo sito web. Puoi trasformare questo elenco ordinario in un elenco di navigazione inserendo <ul> in un elemento <nav>.
L'utilizzo dell'elemento <nav> offre diversi vantaggi. In particolare, uno screen reader annuncia qualcosa come "navigazione" quando l'utente interagisce con l'elemento e aggiunge un punto di riferimento alla pagina. I punti di riferimento sono regioni speciali della pagina, come <header>, <footer> o <main>, a cui uno screen reader può passare. Avere punti di riferimento in una pagina può essere utile, perché consente agli utenti di screen reader di accedere direttamente alle regioni importanti della pagina senza dover interagire con il resto della pagina. Ad esempio, puoi passare da un punto di riferimento all'altro premendo il tasto D in NVDA. In VoiceOver puoi utilizzare il rotore per elencare tutti i punti di riferimento della pagina premendo VO + U.
In questo elenco vedi 4 punti di riferimento: banner, che è l'elemento <header>, navigazione, che è l'elemento <nav>, principale, che è l'elemento <main>, e informazioni sui contenuti, che è l'elemento <footer>. Questo elenco non deve essere troppo lungo, in quanto devi contrassegnare come punti di riferimento solo le parti critiche della UI, come la ricerca sul sito, una navigazione locale o una paginazione.
Se hai una navigazione in tutto il sito, una navigazione locale per la pagina e una paginazione su una singola pagina, potresti avere anche tre elementi <nav>. Va bene, ma ora ci sono tre punti di riferimento per la navigazione e semanticamente sembrano tutti uguali. È difficile distinguerli, a meno che tu non conosca molto bene la struttura della pagina.
Per renderli distinguibili, devi etichettarli utilizzando aria-labelledby o 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>
Se l'etichetta che hai scelto esiste già in un punto della pagina, puoi utilizzare aria-labelledby e fare riferimento all'etichetta esistente utilizzando l'attributo 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>
Un'etichetta concisa è sufficiente, non essere troppo prolisso. Ometti espressioni come "navigazione" o "menu" perché lo screen reader fornisce già queste informazioni agli utenti.
Nascondi la navigazione nelle aree visibili strette
Personalmente, non sono un grande fan di nascondere la navigazione principale su aree visibili strette, ma se l'elenco di link diventa troppo lungo, non c'è altro modo. In questo caso, anziché l'elenco, gli utenti vedono un pulsante con l'etichetta "Menu" o un'icona a forma di hamburger o una combinazione. Se fai clic sul pulsante, l'elenco viene visualizzato e nascosto. Se conosci le nozioni di base di JavaScript e CSS, è un'attività fattibile, ma ci sono diversi aspetti relativi a UX e accessibilità di cui devi occuparti.
- Devi nascondere l'elenco in modo accessibile.
- La navigazione deve essere accessibile da tastiera.
- La navigazione deve comunicare se è visibile o meno.
Aggiunta di un pulsante hamburger
Poiché stai seguendo il principio del potenziamento progressivo, devi assicurarti che la navigazione funzioni ancora e abbia senso anche con JavaScript disattivato.
La prima cosa di cui ha bisogno la navigazione è un pulsante hamburger. Lo crei in HTML in un elemento template, lo cloni in JavaScript e lo aggiungi alla navigazione.
<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>
- L'attributo
aria-expandedindica al software di screen reader se l'elemento controllato dal pulsante è espanso o meno. aria-labelassegna al pulsante un cosiddetto nome accessibile, un'alternativa testuale per l'icona del menu extra.- Nascondi
<svg>dalle tecnologie per la disabilità utilizzandoaria-hiddenperché ha già un'etichetta di testo fornita daaria-label. aria-controlsindica alle tecnologie per la disabilità che supportano l'attributo (ad esempio JAWS) quale elemento è controllato dal pulsante.
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);
- È utile per gli utenti avere la possibilità di chiudere la navigazione quando vogliono, ad esempio premendo il tasto Esc.
- È importante utilizzare
insertBeforeanzichéappendChildperché il pulsante deve essere il primo elemento della navigazione. Se un utente di tastiera o screen reader preme Tab dopo aver fatto clic sul pulsante, si aspetta di attivare il primo elemento dell'elenco. Se il pulsante si trova dopo l'elenco, non è così.
Ora reimposta lo stile predefinito del pulsante e assicurati che sia visibile solo su aree visibili strette.
@media (min-width: 48em) {
nav {
--nav-button-display: none;
}
}
/* Reset button styling */
button {
all: unset;
display: var(--nav-button-display, flex);
}
Nascondere l'elenco
Prima di nascondere l'elenco, posiziona e applica uno stile alla navigazione e all'elenco in modo che il layout sia ottimizzato per le finestre di visualizzazione strette, ma abbia comunque un bell'aspetto sugli schermi più grandi.
Innanzitutto, rimuovi l'elemento <nav> dal flusso naturale della pagina e posizionalo nell'angolo superiore della sezione visibile.
@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;
}
Poi, modifica il layout per le aree visibili strette aggiungendo una nuova proprietà personalizzata (—-nav-list-layout). Il layout è a colonne per impostazione predefinita e passa a righe sugli schermi più grandi.
@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;
}
La navigazione dovrebbe avere un aspetto simile al seguente su viewport stretti.
L'elenco ha ovviamente bisogno di un po' di CSS. Lo sposteremo nell'angolo in alto, lo faremo riempire l'intero schermo in verticale, applicheremo un background-color e un 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;
}
L'elenco dovrebbe avere un aspetto simile a questo nelle aree visibili strette, più simile a una barra laterale che a un semplice elenco.
Infine, nascondi l'elenco, mostralo solo quando l'utente fa clic sul pulsante una volta e nascondilo quando fa di nuovo clic. È importante nascondere solo l'elenco e non l'intera navigazione, perché nascondere la navigazione significherebbe anche nascondere un punto di riferimento importante.
In precedenza, hai aggiunto un evento di clic al pulsante per attivare/disattivare il valore dell'attributo aria-expanded. Puoi utilizzare queste informazioni come condizione per mostrare e nascondere l'elenco in 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);
}
È importante utilizzare una dichiarazione di proprietà come visibility: hidden o display: none anziché opacity: 0 o translateX(100%) per nascondere l'elenco. Queste proprietà assicurano che i link non siano attivabili quando la navigazione è nascosta. L'utilizzo di opacity o translate rimuoverà i contenuti visivamente, quindi i link saranno invisibili, ma comunque accessibili utilizzando la tastiera, il che potrebbe creare confusione e frustrazione. L'utilizzo di visibility o display nasconde visivamente l'elemento e lo rende inaccessibile, nascondendolo quindi a tutti gli utenti.
Animazione dell'elenco
Se ti stai chiedendo perché utilizzare visibility: hidden; anziché display: none;, è perché puoi animare la visibilità. Ha solo due stati, hidden e visible, ma puoi combinarlo con un'altra proprietà come transform o opacity per creare un effetto di scorrimento o di dissolvenza in entrata. Questo non funzionerebbe con display: none perché la proprietà display non è animabile.
Il seguente CSS esegue la transizione di opacity per creare un effetto di dissolvenza in entrata e in uscita.
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);
}
Se invece vuoi animare il movimento, ti consigliamo di inserire la proprietà transition in una query supporti prefers-reduced-motion, perché le animazioni possono causare nausea, vertigini e mal di testa in alcuni utenti.
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);
}
In questo modo, l'animazione verrà visualizzata solo dalle persone che non hanno preferenze per il movimento ridotto.
Migliora lo stile dello stato attivo
Gli utenti che utilizzano la tastiera si affidano agli stili di stato attivo degli elementi per l'orientamento e la navigazione in una pagina. Gli stili di stato attivo predefiniti sono migliori di quelli assenti (cosa che accade se imposti outline: none), ma avere stili di stato attivo personalizzati più chiaramente visibili migliora l'esperienza utente.
Ecco come appaiono gli stili di stato attivo predefiniti sul link in Chrome 103.
Puoi migliorare questo aspetto fornendo i tuoi stili con i tuoi colori. Utilizzando :focus-visible anziché :focus, consenti al browser di decidere quando è opportuno mostrare gli stili di stato attivo. Gli stili :focus saranno visibili a tutti gli utenti che utilizzano mouse, tastiera e touch, indipendentemente dal fatto che ne abbiano bisogno o meno. Con :focus-visible, il browser utilizza l'euristica interna per decidere se mostrarli solo agli utenti della tastiera o a tutti.
/* 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;
}
Supporto dei browser per :focus-visible
Esistono diversi modi per evidenziare gli elementi quando sono selezionati. Ti consigliamo di utilizzare la proprietà outline perché non interrompe il layout, cosa che potrebbe accadere con border, e funziona bene con la modalità Contrasto elevato su Windows. Le proprietà che non funzionano bene sono background-color o box-shadow, perché potrebbero non essere visualizzate affatto con le impostazioni di contrasto personalizzate.
Complimenti! Hai creato una navigazione principale con potenziamento progressivo, semanticamente ricca, accessibile e ottimizzata per il mobile.
C'è sempre qualcosa che può essere migliorato, ad esempio:
- Potresti valutare la possibilità di intrappolare lo stato attivo all'interno della navigazione o di rendere inerte il resto della pagina nelle aree visibili strette.
- Puoi aggiungere uno skip link nella parte superiore della pagina per consentire agli utenti che utilizzano la tastiera di saltare la navigazione.
Se ricordi come è iniziato questo articolo, con l'obiettivo che la soluzione non fosse"né troppo semplice né troppo complicata", è proprio qui che ci troviamo ora. Tuttavia, è possibile progettare una navigazione eccessivamente complessa.
Navigazioni e menu
Esiste una chiara differenza tra navigazioni e menu. Le navigazioni sono raccolte di link per la navigazione tra documenti correlati. I menu sono raccolte di azioni da eseguire in un documento. A volte queste attività si sovrappongono. Potresti avere una navigazione che include anche un pulsante che esegue un'azione, come l'apertura di una finestra modale, o un menu in cui un'azione consiste nella navigazione verso un'altra pagina, come una pagina di assistenza. In questo caso, è importante non combinare i ruoli ARIA, ma identificare lo scopo principale del componente e scegliere il markup e i ruoli di conseguenza.
L'elemento <nav> ha un ruolo ARIA implicito di navigazione, sufficiente per comunicare che l'elemento è una navigazione, ma spesso i siti utilizzano anche menu, menubar e menuitem. Poiché a volte utilizziamo questi termini in modo intercambiabile, potresti pensare che combinarli per migliorare l'esperienza degli utenti di screen reader possa avere senso. Prima di scoprire perché di solito non è così, diamo un'occhiata alla definizione ufficiale di questi ruoli.
Il ruolo di navigatore
Una raccolta di elementi di navigazione (di solito link) per navigare nel documento o nei documenti correlati.
navigation (role) WAI-ARIA 1.1
Il ruolo menu
Un menu è spesso un elenco di azioni o funzioni comuni che l'utente può richiamare. Il ruolo menu è appropriato quando un elenco di voci di menu viene presentato in modo simile a un menu in un'applicazione desktop.
menu (role) WAI-ARIA 1.1
Il ruolo menubar
Una presentazione del menu che di solito rimane visibile e viene presentata in orizzontale. Il ruolo menubar viene utilizzato per creare una barra dei menu simile a quelle presenti nelle applicazioni desktop di Windows, Mac e Gnome. Una barra dei menu viene utilizzata per creare un insieme coerente di comandi di uso frequente. Gli autori devono assicurarsi che l'interazione con la barra dei menu sia simile a quella tipica di una barra dei menu in una Graphic User Interface desktop.
menubar (role) WAI-ARIA 1.1
Il ruolo menuitem
Un'opzione in un insieme di scelte contenute in un menu o in una barra dei menu.
menuitem (role) WAI-ARIA 1.1
La specifica è molto chiara: utilizza l'elemento navigation per navigare nel documento o nei documenti correlati e l'elemento menu solo per un elenco di azioni o funzioni simili ai menu delle applicazioni desktop. Se non stai creando il prossimo Documenti Google, probabilmente non hai bisogno di nessuno dei ruoli di menu per la navigazione principale.
Quando è opportuno utilizzare un menu?
L'utilizzo principale delle voci di menu non è la navigazione, ma l'esecuzione di azioni. Supponiamo che tu abbia un elenco o una tabella di dati e che gli utenti possano eseguire determinate azioni su ogni elemento dell'elenco. Puoi aggiungere un pulsante a ogni riga e mostrare le azioni quando gli utenti fanno clic sul pulsante.
<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>
Implicazioni dell'utilizzo dei ruoli del menu
È molto importante utilizzare questi ruoli di menu con attenzione perché molte cose possono andare storte.
I menu prevedono una determinata struttura DOM. menuitem deve essere un elemento secondario diretto di menu. Il seguente codice potrebbe interrompere il comportamento semantico:
<!-- Wrong, don't do this -->
<ul role="menu">
<li>
<a href="#" role="menuitem">Item 1</a>
</li>
</ul>
Gli utenti esperti si aspettano che determinate scorciatoie da tastiera funzionino con i menu e le barre dei menu. In base alla guida ARIA Authoring Practices Guide (APG), sono inclusi:
- Invio e barra spaziatrice per selezionare le voci di menu.
- Tasti Freccia in tutte le direzioni per spostarti tra gli elementi.
- I tasti Home e Fine per spostare lo stato attivo rispettivamente sul primo o sull'ultimo elemento.
- A-Z per spostare lo stato attivo di selezione alla voce di menu successiva con un'etichetta che inizia con il carattere digitato.
- Esc per chiudere il menu.
Se uno screen reader rileva un menu, il software potrebbe cambiare automaticamente la modalità di navigazione, consentendo l'utilizzo delle scorciatoie menzionate in precedenza. Gli utenti di screen reader meno esperti potrebbero non essere in grado di utilizzare il menu perché non conoscono queste scorciatoie o non sanno come utilizzarle.
Lo stesso vale per gli utenti che utilizzano la tastiera e che potrebbero aspettarsi di poter utilizzare Maiusc e Maiusc + Tab.
Ci sono molti aspetti da considerare quando crei menu e barre dei menu, a partire dall'opportunità di utilizzarli. Quando crei un sito web tipico, l'elemento nav con un elenco e dei link è tutto ciò di cui hai bisogno. Sono incluse anche le applicazioni a pagina singola (SPA) o le app web. Lo stack sottostante non è importante. A meno che tu non stia creando qualcosa di molto simile a un'applicazione desktop, evita i ruoli di menu.
Risorse aggiuntive
- Fixing Lists di Scott O'hara.
- Don't Use ARIA Menu Roles for Site Nav di Adrian Roselli.
- Menus & Menu Buttons di Heydon Pickering.
- WAI-ARIA menus, and why you should handle them with great care di Marco Zehe.
- Hiding content responsibly di Kitty Giraudel.
- :focus-visible Is Here di Matthias Ott.