Dev Tools & Workflow

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.

The Wux Webtools Team The Wux Webtools Team 8 min czytania Wspomagane przez AI, recenzowane przez ludzi
Illustration of a developer reviewing accessible labels and UI components on a screen.
Spis treści
  1. Etykiety ARIA służą do nadawania nazw, nie do przepraszania
  2. Dostępna nazwa prostym językiem
  3. Pierwsza zasada: preferuj natywny HTML i widoczne etykiety
  4. Kiedy `aria-label` jest właściwym narzędziem
  5. Kiedy `aria-label` jest złym narzędziem
  6. Sięgaj po `aria-labelledby`, gdy widoczny tekst już istnieje
  7. Używaj `aria-describedby` dla tekstu pomocy, nie dla nazwy
  8. Powtarzające się kontrolki potrzebują unikalnych nazw
  9. Nie etykietuj wszystkiego
  10. Sprawdzaj obliczoną nazwę, nie tylko kod
  11. Praktyczna lista kontrolna do przeglądu
  12. 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:

  1. Czy rola jest taka, jakiej oczekujesz?
  2. Czy dostępna nazwa jest jasna i konkretna?
  3. 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.

Najczęściej zadawane pytania

Czy każdy przycisk powinien mieć aria-label?
Nie. Przycisk z jasnym widocznym tekstem zwykle ma już dobrą dostępną nazwę. Dodawaj `aria-label` tylko wtedy, gdy widocznego tekstu brakuje albo jest niewystarczający, na przykład w przycisku tylko z ikoną lub powtarzającym się przycisku „Delete”, który potrzebuje kontekstu.
Jaka jest różnica między aria-label a aria-labelledby?
`aria-label` podaje tekst bezpośrednio w atrybucie. `aria-labelledby` wskazuje istniejący tekst w innym miejscu strony. Jeśli odpowiedni widoczny tekst już istnieje, `aria-labelledby` jest zwykle łatwiejsze w utrzymaniu.
Czy aria-label może naprawić div użyty jako przycisk?
Może nadać nazwę, ale nie sprawi, że element będzie zachowywał się jak prawdziwy przycisk. Nadal trzeba obsłużyć zachowanie klawiatury, fokus, stany i oczekiwaną semantykę. W większości przypadków użyj natywnego `<button>`.
Czy aria-label powinna dokładnie odpowiadać widocznemu tekstowi?
Zwykle powinna zawierać widoczny tekst, zwłaszcza w przypadku kontrolek interaktywnych. Wspiera to użytkowników rozpoznawania mowy i spełnia intencję wytycznych WCAG dotyczących etykiety w nazwie.
Skąd mam wiedzieć, co ogłosi czytnik ekranu?
Zacznij od sprawdzenia drzewa dostępności w narzędziach developerskich przeglądarki pod kątem roli, nazwy i opisu. Następnie przetestuj krytyczne interakcje z prawdziwym czytnikiem ekranu, takim jak VoiceOver, NVDA, TalkBack lub JAWS.

Źródła i dalsza lektura

  1. WAI-ARIA Authoring Practices Guide
  2. MDN: aria-label attribute
  3. Accessible Name and Description Computation 1.2
  4. WCAG 2.2 Success Criterion 2.5.3: Label in Name
O autorze
The Wux Webtools Team

Ostatnia aktualizacja:

Czytaj dalej