Dostępność cyfrowa w praktyce – wiedza, narzędzia i inspiracje
Wpisy na blogu
- WCAG 2.2 - kolejny krok
- Aria (atrybuty opisujące)
- Jak opisywać przyciski
- OKLCH kolory, które robią różnicę
- Opisy obrazków
- Małe ekrany, wielkie wyzwania
Aria (atrybuty opisujące)
2025-06-09
ARIA (Accessible Rich Internet Applications) to zestaw atrybutów, które wspierają osoby korzystające z czytników ekranu. Na wielu stronach internetowych elementy takie jak przyciski, formularze czy rozwijane panele są w pełni zrozumiałe wizualnie, ale mogą być nieczytelne dla kogoś, kto nie widzi ekranu lub nie posługuje się myszką. I właśnie tu z pomocą przychodzi ARIA.
To narzędzia, które pozwalają opisać, co dokładnie dzieje się na stronie. Możemy przekazać użytkownikowi: „to jest przycisk”, „tu trwa ładowanie”, „w tym miejscu otworzył się dialog”. To trochę tak, jakbyśmy opowiadali, co się dzieje na scenie komuś, kto jej nie widzi — spokojnie, jasno i bez zbędnych komplikacji.
Zacznijmy od atrybutów opisujących ARIA - to te, które mówią, jak coś się nazywa lub co znaczy.
aria-label
Atrybut aria-label pozwala dodać nazwę (etykietę) do elementu, który sam w sobie nie ma widocznego tekstu. Dzięki temu osoby korzystające z czytników ekranu wiedzą, co dany element robi — nawet jeśli nie ma tam żadnego napisu.
To bardzo przydatne w przypadku ikon, przycisków tylko z grafiką, interaktywnych elementów grupujących (div), a także w formularzach, gdzie np. nie chcemy używać klasycznego - label. Czytnik ekranu przeczyta zawartość z aria-label tak, jakby to był tekst widoczny dla użytkownika.
<button aria-label="Zamknij okno">
<img src="close.svg" alt="">
</button>
To co widzicie powyżej to bardzo popularne wykorzystanie aria. Dla czytnika sytuacja jest zrozumiała - “Zamknij okno, przycisk”, bo aria-label nadaje nazwę całemu elementowi – niezależnie od tego, co zawiera w środku. Czytnik nie analizuje wtedy zawartości, czy tam jest obrazek, SVG, div, nic – po prostu czyta etykietę z aria-label.
I teraz powinna się zacząć seria pytań. Dlaczego wykorzystaliśmy aria-label jako parametr button, a nie wpisałem alt przy obrazku. Mój kod mógłby wyglądać tak:<button><img src="close.svg" alt="Zamknij okno"></button>
Czytnik przeczyta dokładnie tą samą informację - “Zamknij okno, przycisk”. Jaka zatem jest różnica?
Obie wersje są semantycznie poprawne – ale aria-label daje większą kontrolę i lepiej sprawdza się, gdy chcesz uniezależnić opis od grafiki. Aria wykorzystasz gdy grafika nie wnosi dodatkowej treści – jest tylko ikoną np. funkcji. Gdy tekst etykiety chcesz kontrolować technicznie, niezależnie od zawartości obrazka. Gdy zależy Ci na większej elastyczności (np. możesz później łatwo dodać aria-describedby, zmienić aria-label przez JavaScript itd.). I w końcu, gdy ta sama grafika może mieć różne znaczenie w zależności od kontekstu.
Zatem, dopisz alt do ikony będącej przyciskiem, gdy masz pewność, że alt w pełni opisuje działanie tego przycisku lub gdy zależy ci na prostym i lekkim kodzie, bez nadmiarowych atrybutów. Kluczem jest kontekst i przejrzystość dla użytkownika korzystającego z czytnika.
Niektórzy z was, od razu zapytają - jeśli więc alt i aria-label przekazały podobną treść, dlaczego nie stosować wszędzie aria-label i zapomnieć o alt - tak jak poniżej?
<button>
<img src="close.svg" aria-label="Zamknij okno">
</button>
Bo aria-label nie powinno zastępować alt na obrazkach. To właśnie alt jest semantycznym i zgodnym z HTML sposobem opisania zawartości grafiki. Czytnik ekranu przeczyta ten tekst jako nazwę grafiki. To błąd. Czytnik nie przeczyta aria-label z obrazka, a w efekcie użytkownik nic nie usłyszy lub usłyszy tylko „grafika”.
Podsumowując, używaj alt dla obrazków, a aria-label dla elementów interaktywnych, takich jak button, div, a. Nie używaj aria-label zamiast alt na grafice, ale możesz użyć obu rzeczy razem, np. aria-label na przycisku i alt=”” na obrazku, by grafikę pominąć dla czytnika.
aria-labelledby
aria-labelledby to atrybut, który pozwala połączyć element z tekstem opisującym go – ale zamiast wpisywać ten opis bezpośrednio, wskazujemy inny element, którego treść ma zostać użyta jako etykieta. Dzięki temu użytkownik korzystający z czytnika ekranu usłyszy opis, który wynika z zawartości wskazanego elementu, a nie ze sztucznie nadanego tekstu.
To szczególnie przydatne na bardziej złożonych stronach, gdzie standardowe powiązanie np. label i input nie wystarcza. Przykładowo – gdy masz pole formularza, a jego opis składa się z kilku kawałków tekstu, nagłówka albo ikon z podpisami – możesz połączyć wszystko jednym aria-labelledby, wskazując identyfikatory tych elementów. Czytnik scali je i odczyta jako jeden opis.
Dzięki temu zachowujesz pełną kontrolę nad tym, jak użytkownik z technologiami asystującymi będzie odbierał treść, bez konieczności powielania tekstu czy osadzania go wewnątrz każdego komponentu.
<label id="email-label">Twój adres e-mail</label>
<input type="email" aria-labelledby="email-label">
Użytkownik korzystający z czytnika ekranu, gdy skupi się na polu input, usłyszy: Twój adres e-mail, pole edycji lub podobny komunikat w zależności od używanego czytnika.
Dlaczego? Bo aria-labelledby="email-label" mówi czytnikowi, że etykietą tego pola jest tekst z elementu o id="email-label". Czytnik pobierze ten tekst – „Twój adres e-mail” – i przeczyta go jako nazwę tego pola formularza. Dodaje też domyślny opis, że to „pole edycji”, bo rozpoznaje type="email" jako edytowalne pole.
Dzięki temu użytkownik wie, czego dotyczy pole i co ma tam wpisać – a to właśnie cel dobrze użytej dostępności.
aria-describedby
Użycie aria-describedby pozwala rozbudować komunikat dla użytkownika – bez mieszania tego z główną etykietą. Daje to jasność: jedno mówi co to jest, drugie – co warto wiedzieć. Świetnie sprawdza się np. przy polach z podpowiedziami, błędami czy wymaganiami (np. „Hasło musi mieć co najmniej 8 znaków”).
<label for="password">Hasło</label>
<input type="password" id="password" aria-describedby="password-help">
<p id="password-help">Hasło musi mieć co najmniej 8 znaków</p>
Użytkownik najpierw usłyszy etykietę pola – Hasło. To dzieje się dzięki powiązaniu label z polem input przez atrybut for. Następnie czytnik automatycznie odczyta dodatkową informację, która znajduje się w elemencie p wskazanym przez aria-describedby. W tym przypadku czytnik przeczyta Hasło musi mieć co najmniej 8 znaków.
Dla użytkownika oznacza to, że po wejściu w pole hasła od razu wie, czego się od niego oczekuje. Nie musi szukać opisu gdzieś obok, bo informacja jest odczytywana naturalnie, bez dodatkowych działań. To rozwiązanie jest wygodne, dostępne i zgodne z zasadami WCAG – poprawia zrozumiałość formularzy i zmniejsza ryzyko błędów przy ich wypełnianiu.
W kolejnym wpisie, zajmiemy się atrybutami dynamicznymi aria.