Errori e fix

aria-label sui bottoni: quando aiuta e quando rompe il nome accessibile

aria-label sostituisce il testo visibile, non lo completa. Se il valore non contiene la scritta del bottone, chi usa il riconoscimento vocale non riesce a premere il comando che vede.

In sintesi

  • Un bottone con testo visibile non ha bisogno di aria-label: il nome accessibile è già il testo.
  • Se aggiungi aria-label, il valore deve iniziare con il testo visibile: «Salva bozza», non «Invia il modulo».
  • Per un bottone di sola icona, aria-label è obbligatorio e deve descrivere l'azione.

Risposta breve: un bottone con testo visibile ha già il suo nome accessibile. Aggiungere aria-label lo sostituisce, non lo completa. Se il valore non contiene la scritta visibile, chi usa il riconoscimento vocale non riesce a premere il comando che vede.

Le tre forme del nome accessibile

ElementoNome accessibileUso corretto
<button>Salva</button>«Salva»nessun attributo aggiuntivo
bottone con sola iconaassente senza aiutoaria-label="Chiudi"
bottone con testo e iconail testoaria-hidden sull'icona

Perché il nome viene sostituito

Il motivo sta nell'ordine di calcolo. Il nome accessibile non è un attributo: è un valore calcolato, e la specifica Accessible Name and Description Computation elenca le fonti in sequenza. Prima un autore che punta altrove con aria-labelledby, poi aria-label, poi il contenuto del nodo. aria-label non allunga quella lista: si colloca sopra il testo e lo copre. Il testo visibile resta sullo schermo e sparisce dall'albero di accessibilità, ed è la ragione per cui il valore deve contenerlo.

La regola viene da WCAG 2.5.3, Label in Name: il nome accessibile deve contenere il testo visibile. Non deve essere identico, ma deve iniziare con le stesse parole.

L'errore tipico

// sbagliato: il nome accessibile non contiene «Salva»
Salva

// corretto: il testo visibile è già sufficiente
Salva

// corretto: icona decorativa nascosta, azione nel nome

  

Nel secondo caso l'icona non deve essere annunciata: senza aria-hidden, un SVG con un titolo può aggiungere parole al nome e produrre un annuncio doppio.

Quando l'etichetta è fuori dal bottone

Salva la bozza senza pubblicare
Salva

Come leggerlo in dieci secondi

// DevTools → Console: elenca i bottoni il cui nome non contiene il testo visibile
[...document.querySelectorAll("button")].forEach((b) => {
  const label = b.getAttribute("aria-label");
  if (!label) return;
  const visible = (b.textContent || "").trim().toLowerCase();
  if (visible && !label.toLowerCase().includes(visible)) console.warn(b, label);
});

Lo stesso controllo si fa senza codice: apri il pannello Elements, seleziona il bottone e leggi Computed name nella scheda Accessibility di Chrome o Firefox. Se accanto al nome compare from attribute, la fonte è l'attributo e non il testo. Il confronto con quello che l'utente vede dura un secondo.

aria-labelledby punta a testo visibile: è preferibile a aria-label perché il nome resta tradotto dal contenuto, non duplicato in un attributo.

Quando la correzione non funziona

Se il nome letto dallo screen reader non cambia, controlla la precedenza: aria-labelledby vince su aria-label, che vince sul contenuto. Un aria-label="" vuoto non cancella il nome, mentre aria-label con uno spazio sì: è un caso da evitare, perché rende il bottone anonimo. Sui bottoni di sola icona, il title non è un sostituto affidabile.

Quando la correzione tipica peggiora le cose

La correzione più diffusa è allineare l'attributo alla scritta: aria-label="Salva bozza" accanto a Salva bozza. Funziona oggi. Il problema è che la stessa frase ora vive in due posti, l'attributo e il contenuto, e il file di traduzione tocca solo il secondo. Alla revisione successiva del copy l'attributo resta in una lingua e il testo nell'altra: il nome calcolato torna a non contenere la scritta visibile, e nessuno lo nota, perché ogni stringa letta da sola sembra corretta.

Il limite di questa regola

Un limite da dire chiaro: il criterio 2.5.3 riguarda solo i controlli con un'etichetta visibile. Un bottone di sola icona ne resta fuori, e nessun controllo automatico dice se l'ordine di lettura è sensato. axe e Lighthouse segnalano il nome mancante, mai un nome che sostituisce male il testo: un test verde non prova che il comando sia pronunciabile.

Come prevenirlo

  • Un bottone con testo visibile non riceve aria-label.
  • Ogni icona decorativa ha aria-hidden="true".
  • Nel test, leggi il nome accessibile dal pannello Accessibility e confrontalo con il testo visibile.
  • Le parole del nome accessibile vivono in un solo posto: il contenuto visibile o aria-labelledby, mai copiate in un attributo.

Dove continuare

Nel catalogo: form di login, componenti e blocchi. Le guide: checklist di accessibilità e palette con contrasto misurato; il confronto: Radix, Base UI e React Aria.

Domande frequenti

Perché aria-label è pericoloso su un bottone con testo?

Sostituisce il nome accessibile. Un utente che dice «clicca Salva» non trova corrispondenza se il nome è «Invia il modulo».

Cosa uso per un'icona?

Un'icona decorativa va nascosta con aria-hidden="true"; il bottone riceve aria-label con l'azione, per esempio «Chiudi».

aria-label e aria-labelledby insieme?

No: se entrambi sono presenti, aria-labelledby vince e il valore di aria-label viene ignorato. Scegli uno dei due.

Posso usare il title come etichetta?

No. Il title è un suggerimento, non un nome accessibile affidabile: molti screen reader lo ignorano.

Come verifico il nome accessibile?

Con il pannello Accessibility degli strumenti del browser: mostra il nome calcolato. Se non contiene il testo visibile, c'è un problema.