Przewodnik dla developerów po etykietach ARIA, które naprawdę pomagają
Etykiety ARIA nie są magiczną warstwą dostępności. Użyte dobrze, sprawiają, że kontrolki są zrozumiałe. Użyte niedbale, ukrywają przydatny tekst i tworzą mylące interfejsy.
Spis treści
- Etykiety ARIA służą do nadawania nazw, nie do przepraszania
- Dostępna nazwa prostym językiem
- Pierwsza zasada: preferuj natywny HTML i widoczne etykiety
- Kiedy `aria-label` jest właściwym narzędziem
- Kiedy `aria-label` jest złym narzędziem
- Sięgaj po `aria-labelledby`, gdy widoczny tekst już istnieje
- Używaj `aria-describedby` dla tekstu pomocy, nie dla nazwy
- Powtarzające się kontrolki potrzebują unikalnych nazw
- Nie etykietuj wszystkiego
- Sprawdzaj obliczoną nazwę, nie tylko kod
- Praktyczna lista kontrolna do przeglądu
- Cicha dyscyplina dobrej ARIA
Etykiety ARIA służą do nadawania nazw, nie do przepraszania
ARIA jest przydatna, ale często używa się jej jako łaty na niejasny HTML. Właśnie wtedy zespoły wpadają w kłopoty.
Najczęstszy przykład to aria-label. Wygląda niewinnie: dodać tekst, zadowolić linter, iść dalej. Ale dostępna nazwa nie jest dekoracją. To nazwa, którą wiele technologii asystujących prezentuje użytkownikom, gdy poruszają się po przyciskach, linkach, polach formularzy, nagłówkach, landmarkach i kontrolkach.
Jeśli ta nazwa jest niejasna, zdublowana, nieaktualna albo różni się od widocznej etykiety, interfejs staje się trudniejszy w użyciu. Czasem jest gorzej: aria-label może nadpisać lepszy tekst, który już był obecny w DOM.
Celem nie jest dodanie większej ilości ARIA. Celem jest uczynienie nazwy, roli, stanu i przeznaczenia każdego elementu interfejsu jasnymi.
Dostępna nazwa prostym językiem
Większość elementów interaktywnych ma dostępną nazwę. Czytniki ekranu używają tej nazwy, aby ogłosić, czym jest dany element.
Na przykład:
<button>Save changes</button>
Czytnik ekranu może ogłosić coś w rodzaju: „Save changes, przycisk”. Rola wynika z natywnego elementu button. Nazwa pochodzi z tekstu w jego środku.
To jest idealny przypadek: widoczny tekst i dostępna nazwa są zgodne.
Atrybuty etykietowania ARIA stają się przydatne wtedy, gdy widoczny interfejs nie zapewnia pełnej nazwy albo gdy nazwa musi pochodzić z innego elementu. Główne atrybuty to:
aria-label: podaje tekst bezpośrednio na elemencie.aria-labelledby: wskazuje jeden lub więcej elementów, których tekst staje się nazwą.aria-describedby: wskazuje pomocniczy tekst opisu, a nie główną nazwę.
Te trzy atrybuty są ze sobą powiązane, ale nie są zamienne.
Pierwsza zasada: preferuj natywny HTML i widoczne etykiety
Jeśli możesz umieścić widoczny tekst na kontrolce, zrób to najpierw.
To jest lepsze:
<button>Delete invoice</button>
Niż to:
<button aria-label="Delete invoice">
<svg aria-hidden="true" focusable="false">...</svg>
</button>
Drugi wzorzec jest poprawny dla przycisku składającego się tylko z ikony. Ale jeśli projekt może zaakceptować widoczny tekst, widoczny tekst pomaga wszystkim: użytkownikom czytników ekranu, użytkownikom rozpoznawania mowy, osobom obciążonym poznawczo, osobom szybko skanującym stronę oraz osobom używającym narzędzi tłumaczeniowych.
To powracający motyw w pracy nad dostępnością. Natywny HTML i widoczne wskazówki rozwiązują więcej problemów niż ukryte metadane. Ta sama zasada dotyczy szerzej semantyki przycisków; jeśli Twój zespół audytuje kontrolki UI, nasza lista kontrolna dla dostępnych przycisków internetowych będzie dobrym uzupełnieniem tego przewodnika.
Kiedy aria-label jest właściwym narzędziem
Używaj aria-label, gdy element potrzebuje dostępnej nazwy i nie ma odpowiedniego widocznego tekstu, do którego można się odwołać.
Klasyczny przypadek to przycisk tylko z ikoną:
<button aria-label="Search">
<svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
<!-- icon -->
</svg>
</button>
To rozsądne rozwiązanie. Widoczna ikona sugeruje wyszukiwanie, ale sama ścieżka SVG nie zapewnia wiarygodnej nazwy. aria-label ją dostarcza.
Inne dobre przypadki to:
- Przycisk zamykania przedstawiony tylko jako „X”.
- Landmark nawigacji, który potrzebuje bardziej szczegółowej nazwy, na przykład
aria-label="Product". - Powtarzająca się kontrolka, w której widoczny kontekst nie jest częścią tekstu przycisku.
Na przykład:
<nav aria-label="Primary">
...
</nav>
<nav aria-label="Footer">
...
</nav>
Oba są landmarkami nawigacji, ale ich etykiety pomagają użytkownikom odróżnić je podczas poruszania się po landmarkach.
Kiedy aria-label jest złym narzędziem
Nie dodawaj aria-label tylko dlatego, że test mówi, iż element potrzebuje etykiety. Najpierw napraw znaczniki.
Źle:
<div role="button" tabindex="0" aria-label="Submit">Submit</div>
Lepiej:
<button>Submit</button>
Pierwszy przykład tworzy niepotrzebną pracę. Musisz teraz odtworzyć obsługę klawiatury, stany wyłączenia, zachowanie formularza i oczekiwania, które natywne przyciski już zapewniają.
Unikaj też używania aria-label do zmieniania nazwy widocznego tekstu w sposób, który zmienia znaczenie.
<button aria-label="Delete invoice">Remove</button>
Wygląda to na drobiazg, ale może mylić użytkowników polegających na wprowadzaniu głosowym. Jeśli widoczny przycisk mówi „Remove”, ale jego dostępna nazwa to „Delete invoice”, użytkownik próbujący powiedzieć „kliknij Remove” może nie uzyskać oczekiwanego rezultatu. Wymóg WCAG dotyczący „etykiety w nazwie” istnieje dokładnie z tego powodu: widoczny tekst powinien zasadniczo zawierać się w dostępnej nazwie.
Lepsza wersja:
<button aria-label="Remove invoice">Remove</button>
Często jeszcze lepiej:
<button>Remove invoice</button>
Sięgaj po aria-labelledby, gdy widoczny tekst już istnieje
Jeśli tekst etykiety już znajduje się na stronie, aria-labelledby jest zwykle lepsze niż aria-label.
Przykład:
<h2 id="billing-title">Billing address</h2>
<section aria-labelledby="billing-title">
...
</section>
Dostępna nazwa sekcji pochodzi teraz z widocznego nagłówka. Unikasz duplikowania tekstów, co zmniejsza liczbę błędów tłumaczeniowych i nieaktualnych etykiet.
Jest to szczególnie przydatne dla grup formularzy:
<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>
W wielu przypadkach natywne legend wystarcza bez ARIA. Chodzi o to, że widoczne etykiety powinny prowadzić. ARIA powinna łączyć istniejące znaczenie, a nie tworzyć jego drugą, prywatną wersję.
Używaj aria-describedby dla tekstu pomocy, nie dla nazwy
Opis nie jest etykietą.
Rozważ to pole:
<label for="password">Password</label>
<input id="password" type="password" aria-describedby="password-help">
<p id="password-help">Use at least 12 characters.</p>
Dostępna nazwa to „Password”. Opis to „Use at least 12 characters.” Czytnik ekranu może ogłosić oba, ale służą różnym celom.
Nie rób tego:
<input type="password" aria-label="Use at least 12 characters">
To nadaje polu nazwę od instrukcji, a nie od pojęcia. Użytkownik poruszający się po formularzu chce najpierw wiedzieć, czym jest pole, a dopiero potem jakie ograniczenia obowiązują.
To rozróżnienie ma znaczenie także w stanach błędu:
<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>
Etykieta pozostaje stabilna. Komunikat błędu staje się kontekstem pomocniczym.
Powtarzające się kontrolki potrzebują unikalnych nazw
Listy i karty to miejsca, w których etykiety ARIA często stają się potrzebne.
Źle:
<button>Delete</button>
<button>Delete</button>
<button>Delete</button>
Użytkownik czytnika ekranu poruszający się po przyciskach może usłyszeć „Delete, przycisk” trzy razy, bez żadnego kontekstu.
Dobrze:
<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>
To uzasadnione użycie aria-label: widoczny tekst pozostaje zwięzły, a dostępna nazwa zawiera obiekt.
Używaj jednak tego wzorca ostrożnie. Jeśli nazwa obiektu jest widoczna w pobliżu, aria-labelledby może być łatwiejsze w utrzymaniu:
<article>
<h3 id="report-q4">Q4 revenue</h3>
<button aria-labelledby="delete-q4 report-q4" id="delete-q4">Delete</button>
</article>
Dostępna nazwa staje się „Delete Q4 revenue”. Dzięki temu nie duplikujesz tytułu raportu w atrybucie.
Nie etykietuj wszystkiego
Nie każdy element potrzebuje etykiety ARIA.
Tekst statyczny zwykle jej nie potrzebuje. Ikony dekoracyjne też nie. Kontenery również nie, chyba że mają znaczącą rolę landmarku lub widżetu. Nadmierne etykietowanie może sprawić, że strona będzie hałaśliwa i trudniejsza w nawigacji.
W przypadku obrazów używaj modelu właściwego dla obrazów: obrazy znaczące potrzebują użytecznego alt; obrazy dekoracyjne potrzebują pustego alt="". Nie używaj etykiet ARIA jako zamiennika dobrego tekstu alternatywnego dla obrazów. Jeśli Twój zespół miesza te pojęcia, wróć do pragmatycznego tekstu alternatywnego obrazów i oddziel alternatywy dla obrazów od nazw kontrolek.
Częstym błędem jest nadawanie każdemu SVG atrybutu aria-label. Jeśli SVG znajduje się wewnątrz przycisku, a przycisk ma już nazwę, ikona zwykle powinna być ukryta przed technologiami asystującymi:
<button aria-label="Open menu">
<svg aria-hidden="true" focusable="false">...</svg>
</button>
W przeciwnym razie użytkownik może usłyszeć redundantne lub dziwne komunikaty, zależnie od kombinacji przeglądarki i technologii asystującej.
Sprawdzaj obliczoną nazwę, nie tylko kod
Błędy dostępności często przechodzą przez code review, ponieważ znaczniki wyglądają wiarygodnie.
Nowoczesne narzędzia developerskie przeglądarek potrafią pokazać obliczone drzewo dostępności. W Chrome, Edge, Firefox i Safari zbadaj element i poszukaj informacji o dostępności, takich jak rola, nazwa i opis. Sprawdzasz trzy rzeczy:
- Czy rola jest taka, jakiej oczekujesz?
- Czy dostępna nazwa jest jasna i konkretna?
- Czy opis pomaga, nie zastępując nazwy?
Następnie przetestuj kilka przepływów z prawdziwym czytnikiem ekranu. Nie musisz zostać pełnoetatowym ekspertem od technologii asystujących, aby wychwycić podstawy. Na macOS VoiceOver jest wbudowany. Na Windows NVDA jest szeroko używany i darmowy. Na urządzeniach mobilnych testuj z VoiceOver na iOS i TalkBack na Androidzie tam, gdzie ma to znaczenie.
Narzędzia automatyczne są przydatne, ale nie potrafią wiarygodnie stwierdzić, czy „Open”, „Read more” albo „Delete” mają wystarczający kontekst. Traktuj automatyzację jak siatkę, nie jak sędziego. To podobne do audytu wydajności: raport może wskazać podejrzane obszary, ale nadal trzeba zinterpretować wpływ. To samo spokojne podejście, które polecamy przy czytaniu raportu Lighthouse bez paniki, ma zastosowanie tutaj.
Praktyczna lista kontrolna do przeglądu
Przed wdrożeniem etykiet ARIA zapytaj:
- Czy zamiast tego można użyć natywnego HTML?
- Czy istnieje widoczny tekst, który powinien zostać użyty jako etykieta?
- Jeśli widoczny tekst istnieje, czy dostępna nazwa go zawiera?
- Czy powtarzające się kontrolki są unikalne, gdy nawigujemy poza kontekstem wizualnym?
- Czy tekst pomocy jest połączony przez
aria-describedby, a nie wtłoczony w etykietę? - Czy ikony dekoracyjne są ukryte przed technologiami asystującymi?
- Czy ktoś sprawdził obliczoną dostępną nazwę w narzędziach developerskich przeglądarki?
- Czy wykonano przynajmniej jeden przebieg z prawdziwym czytnikiem ekranu dla krytycznego przepływu?
Ta lista kontrolna wychwytuje większość problemów z etykietami, zanim staną się problemami użytkowników.
Cicha dyscyplina dobrej ARIA
Dobra praca z ARIA rzadko jest spektakularna. To przede wszystkim powściągliwość.
Używaj prawdziwych przycisków. Używaj prawdziwych etykiet. Utrzymuj widoczne i dostępne nazwy w zgodzie. Dodawaj aria-label tylko wtedy, gdy nie ma lepszego widocznego źródła. Używaj aria-labelledby, gdy strona już zawiera właściwy tekst. Używaj aria-describedby dla pomocniczych instrukcji i błędów.
Platforma webowa daje developerom wiele za darmo, gdy korzystamy z niej bezpośrednio. ARIA jest po to, by wypełniać luki. Umiejętność polega na rozpoznaniu, kiedy luka naprawdę istnieje.