En utvecklarguide till ARIA-etiketter som faktiskt hjälper
ARIA-etiketter är inte ett magiskt tillgänglighetslager. Rätt använda gör de kontroller begripliga. Slarvigt använda döljer de användbar text och skapar förvirrande gränssnitt.
Innehållsförteckning
- ARIA-etiketter är till för namn, inte ursäkter
- Det tillgängliga namnet, på ren svenska
- Första regeln: föredra inbyggd HTML och synliga etiketter
- När `aria-label` är rätt verktyg
- När `aria-label` är fel verktyg
- Välj `aria-labelledby` när synlig text redan finns
- Använd `aria-describedby` för hjälptext, inte namnet
- Upprepade kontroller behöver unika namn
- Etikettera inte allt
- Kontrollera det beräknade namnet, inte bara koden
- En praktisk granskningschecklista
- Den stillsamma disciplinen i bra ARIA
ARIA-etiketter är till för namn, inte ursäkter
ARIA är användbart, men används ofta som en lagning för otydlig HTML. Det är där team hamnar i problem.
Det vanligaste exemplet är aria-label. Det ser harmlöst ut: lägg till en sträng, gör lintern nöjd och gå vidare. Men ett tillgängligt namn är inte dekoration. Det är namnet som många hjälpmedel visar för användare när de navigerar via knappar, länkar, formulärfält, rubriker, landmärken och kontroller.
Om namnet är vagt, duplicerat, föråldrat eller skiljer sig från den synliga etiketten blir gränssnittet svårare att använda. Ibland ännu värre: aria-label kan åsidosätta bättre text som redan fanns i DOM:en.
Målet är inte att lägga till mer ARIA. Målet är att göra namn, roll, tillstånd och syfte för varje gränssnittselement tydligt.
Det tillgängliga namnet, på ren svenska
De flesta interaktiva element har ett tillgängligt namn. Skärmläsare använder det namnet för att meddela vad elementet är.
Till exempel:
<button>Save changes</button>
En skärmläsare kan säga något i stil med: “Save changes, knapp.” Rollen kommer från det inbyggda button-elementet. Namnet kommer från texten inuti det.
Det är idealfallet: synlig text och tillgängligt namn stämmer överens.
ARIA-attribut för etiketter blir användbara när det synliga gränssnittet inte ger ett fullständigt namn, eller när namnet måste komma från ett annat element. De viktigaste attributen är:
aria-label: anger en sträng direkt på elementet.aria-labelledby: pekar på ett eller flera element vars text blir namnet.aria-describedby: pekar på stödjande beskrivningstext, inte huvudnamnet.
De tre hänger ihop, men är inte utbytbara.
Första regeln: föredra inbyggd HTML och synliga etiketter
Om du kan lägga synlig text på kontrollen, gör det först.
Det här är bättre:
<button>Delete invoice</button>
Än det här:
<button aria-label="Delete invoice">
<svg aria-hidden="true" focusable="false">...</svg>
</button>
Det andra mönstret är giltigt för en knapp som bara består av en ikon. Men om designen kan tåla synlig text hjälper synlig text alla: skärmläsaranvändare, användare av taligenkänning, personer med hög kognitiv belastning, personer som skannar snabbt och personer som använder översättningsverktyg.
Det här är ett återkommande tema i tillgänglighetsarbete. Inbyggd HTML och synliga affordanser löser fler problem än dold metadata. Samma princip gäller knappsemantik mer generellt; om ditt team granskar UI-kontroller är vår checklista för tillgängliga webbknappar ett bra komplement till den här guiden.
När aria-label är rätt verktyg
Använd aria-label när ett element behöver ett tillgängligt namn och det inte finns någon lämplig synlig text att referera till.
Det klassiska fallet är en knapp som bara består av en ikon:
<button aria-label="Search">
<svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
<!-- icon -->
</svg>
</button>
Det här är rimligt. Den synliga ikonen antyder sökning, men SVG-sökvägen i sig ger inget tillförlitligt namn. aria-label tillhandahåller ett.
Andra bra fall är:
- En stängningsknapp som bara representeras av ett “X”.
- Ett navigationslandmärke som behöver ett mer specifikt namn, till exempel
aria-label="Product". - En upprepad kontroll där synlig kontext inte ingår i knapptexten.
Till exempel:
<nav aria-label="Primary">
...
</nav>
<nav aria-label="Footer">
...
</nav>
Båda är navigationslandmärken, men deras etiketter hjälper användare att skilja dem åt när de förflyttar sig mellan landmärken.
När aria-label är fel verktyg
Lägg inte till aria-label bara för att ett test säger att ett element behöver en etikett. Rätta markeringen först.
Dåligt:
<div role="button" tabindex="0" aria-label="Submit">Submit</div>
Bättre:
<button>Submit</button>
Det första exemplet skapar onödigt arbete. Du måste nu återskapa tangentbordsbeteende, inaktiverade tillstånd, formulärbeteende och förväntningar som inbyggda knappar redan ger.
Undvik också att använda aria-label för att byta namn på synlig text på ett sätt som ändrar betydelsen.
<button aria-label="Delete invoice">Remove</button>
Det här ser litet ut, men det kan förvirra användare som förlitar sig på röststyrning. Om en synlig knapp säger “Remove”, men dess tillgängliga namn är “Delete invoice”, kanske en användare som försöker säga “klicka på Remove” inte får det förväntade resultatet. WCAG:s krav “label in name” finns av just den här anledningen: synlig text bör i allmänhet ingå i det tillgängliga namnet.
En bättre version:
<button aria-label="Remove invoice">Remove</button>
Ofta ännu bättre:
<button>Remove invoice</button>
Välj aria-labelledby när synlig text redan finns
Om etiketttexten redan finns på sidan är aria-labelledby vanligtvis bättre än aria-label.
Exempel:
<h2 id="billing-title">Billing address</h2>
<section aria-labelledby="billing-title">
...
</section>
Sektionens tillgängliga namn kommer nu från den synliga rubriken. Du undviker att duplicera strängar, vilket minskar översättningsmisstag och föråldrade etiketter.
Det här är särskilt användbart för formulärgrupper:
<fieldset aria-labelledby="shipping-speed-title">
<legend id="shipping-speed-title">Shipping speed</legend>
<label>
<input type="radio" name="shipping" value="standard">
Standard
</label>
<label>
<input type="radio" name="shipping" value="express">
Express
</label>
</fieldset>
I många fall räcker den inbyggda legend utan ARIA. Poängen är att synliga etiketter ska leda. ARIA ska koppla ihop befintlig betydelse, inte skapa en andra privat version av den.
Använd aria-describedby för hjälptext, inte namnet
En beskrivning är inte en etikett.
Titta på det här fältet:
<label for="password">Password</label>
<input id="password" type="password" aria-describedby="password-help">
<p id="password-help">Use at least 12 characters.</p>
Det tillgängliga namnet är “Password.” Beskrivningen är “Use at least 12 characters.” En skärmläsare kan läsa upp båda, men de fyller olika syften.
Gör inte så här:
<input type="password" aria-label="Use at least 12 characters">
Det namnger fältet efter instruktionen, inte efter begreppet. En användare som navigerar i ett formulär vill först veta vad fältet är, och därefter vilka begränsningar som gäller.
Den här skillnaden spelar roll även vid feltillstånd:
<label for="email">Email</label>
<input
id="email"
type="email"
aria-invalid="true"
aria-describedby="email-error"
>
<p id="email-error">Enter an email address in the format [email protected].</p>
Etiketten förblir stabil. Felmeddelandet blir stödjande kontext.
Upprepade kontroller behöver unika namn
Listor och kort är där ARIA-etiketter ofta blir nödvändiga.
Dåligt:
<button>Delete</button>
<button>Delete</button>
<button>Delete</button>
En skärmläsaranvändare som navigerar via knappar kan höra “Delete, knapp” tre gånger utan kontext.
Bra:
<button aria-label="Delete report: Q4 revenue">Delete</button>
<button aria-label="Delete report: Hiring plan">Delete</button>
<button aria-label="Delete report: Vendor list">Delete</button>
Det här är en legitim användning av aria-label: den synliga texten förblir kort, medan det tillgängliga namnet innehåller objektet.
Men använd det här mönstret varsamt. Om objektnamnet syns i närheten kan aria-labelledby vara mer underhållbart:
<article>
<h3 id="report-q4">Q4 revenue</h3>
<button aria-labelledby="delete-q4 report-q4" id="delete-q4">Delete</button>
</article>
Det tillgängliga namnet blir “Delete Q4 revenue.” Det undviker att rapporttiteln dupliceras i ett attribut.
Etikettera inte allt
Alla element behöver inte en ARIA-etikett.
Statisk text behöver det vanligtvis inte. Dekorativa ikoner behöver det inte. Behållare behöver det inte, om de inte har ett meningsfullt landmärke eller en widgetroll. För många etiketter kan göra en sida brusig och svårare att navigera.
För bilder, använd den bildspecifika modellen: meningsfulla bilder behöver användbar alt; dekorativa bilder behöver tom alt="". Använd inte ARIA-etiketter som ersättning för bra bildtext. Om ditt team blandar ihop de här begreppen, gå tillbaka till pragmatisk alt-text för bilder och separera bildalternativ från kontrollnamn.
Ett vanligt misstag är att ge varje SVG en aria-label. Om SVG:n ligger inuti en knapp och knappen redan har ett namn, bör ikonen vanligtvis döljas för hjälpmedel:
<button aria-label="Open menu">
<svg aria-hidden="true" focusable="false">...</svg>
</button>
Annars kan användaren höra redundanta eller märkliga uppläsningar beroende på kombinationen av webbläsare och hjälpmedel.
Kontrollera det beräknade namnet, inte bara koden
Tillgänglighetsbuggar överlever ofta kodgranskning eftersom markeringen ser rimlig ut.
Moderna utvecklarverktyg i webbläsare kan visa det beräknade tillgänglighetsträdet. I Chrome, Edge, Firefox och Safari kan du inspektera elementet och leta efter tillgänglighetsinformation som roll, namn och beskrivning. Du kontrollerar tre saker:
- Är rollen den du förväntar dig?
- Är det tillgängliga namnet tydligt och specifikt?
- Är beskrivningen hjälpsam utan att ersätta namnet?
Testa sedan några flöden med en riktig skärmläsare. Du behöver inte bli en heltidspecialist på hjälpmedel för att fånga grunderna. På macOS är VoiceOver inbyggt. På Windows används NVDA brett och är gratis. På mobil, testa med VoiceOver på iOS och TalkBack på Android där det är relevant.
Automatiserade verktyg är användbara, men de kan inte på ett tillförlitligt sätt avgöra om “Öppna”, “Läs mer” eller “Ta bort” har tillräcklig kontext. Se automatisering som ett nät, inte som en domare. Det liknar prestandagranskning: en rapport kan peka dig mot misstänkta områden, men du behöver fortfarande tolka påverkan. Samma lugna förhållningssätt som vi rekommenderar för att läsa en Lighthouse-rapport utan panik gäller här.
En praktisk granskningschecklista
Innan du levererar ARIA-etiketter, fråga:
- Skulle detta kunna vara inbyggd HTML i stället?
- Finns det synlig text som bör användas som etikett?
- Om synlig text finns, ingår den i det tillgängliga namnet?
- Är upprepade kontroller unika när de navigeras utanför visuell kontext?
- Är hjälptext kopplad med
aria-describedby, inte intryckt i etiketten? - Är dekorativa ikoner dolda för hjälpmedel?
- Har någon kontrollerat det beräknade tillgängliga namnet i webbläsarens utvecklarverktyg?
- Har minst ett verkligt skärmläsartest gjorts för det kritiska flödet?
Den här checklistan fångar de flesta etikettproblem innan de blir användarproblem.
Den stillsamma disciplinen i bra ARIA
Bra ARIA-arbete är sällan dramatiskt. Det handlar mest om återhållsamhet.
Använd riktiga knappar. Använd riktiga etiketter. Håll synliga och tillgängliga namn i linje. Lägg bara till aria-label när det inte finns någon bättre synlig källa. Använd aria-labelledby när sidan redan innehåller rätt text. Använd aria-describedby för stödjande instruktioner och fel.
Webbplattformen ger utvecklare mycket gratis när vi använder den direkt. ARIA finns där för luckorna. Färdigheten ligger i att veta när det faktiskt finns en lucka.