blog na temat dostępności stron internetowych

Przejdź do głównej treści

ARIA

Dawno, dawno temu, serwisy internetowe stanowiły zbiór statycznych dokumentów HTML. Interaktywne treści były ograniczone do elementów takich jak linki, przyciski czy też pola formularza, które (pod warunkiem, że są odpowiednio oznaczone w kodzie) nie stanowią problemu dla osób korzystających z czytników ekranu. Każdy semantyczny element HTML posiada bowiem szereg automatycznie przypisanych mu właściwości, do których technologie asystujące mają dostęp poprzez tzw. dostępnościowy API.

Czasy się jednak zmieniły. Współczesne strony internetowe często zawierają dynamiczne sekcje, w których treść zmienia się bez konieczności ponownego załadowania strony, oraz niestandardowe (nie mające swojego odpowiednika w HTML) widgety, takie jak zakładki (ang. tabs), akordeony (ang. accordions), itd. Komponenty te stanowią problem dla osób niewidomych i słabowidzących, gdyż zbudowane są albo przy użyciu elementów niesemantycznych (<div>, <span>), albo elementów przeznaczonych do innych celów. Pomimo że ich działanie i rola zostają zmienione przy pomocy JavaScript, ich dostępnościowe API nie ulega zmianie, co znaczy że informacja o ich nowej roli i właściwościach (choć przekazana w warstwie prezentacyjnej za pomocą wizualnych poszlak), nie jest udostępniona technologiom asystującym.

Przykład – zakładki

Spójrzmy na przykład na tzw. zakładki.

przykład komponentu typu tabs, z dwoma zakładkami: Dzisiaj i Jutro

Tradycyjnie tworzyło się je przy pomocy listy zawierającej kontrolki oraz przyporządkowanych im sekcji, np.

<h2>Wydarzenia</h2>
<ul>
  <li>Dzisiaj</li>
  <li><a href="#">Jutro</a></li>
</ul>
<section>
  <h3 class="hidden">Dzisiaj</h3>
  <p>*** Opis dzisiejszych wydarzeń ***</p>
</section>
<!-- poniższa sekcja jest ukryta -->
<section style="display: none">
  <h3 class="hidden">Jutro</h3>
  <p>*** Jutrzejsze wydarzenia ***</p>
</section>

Przy pomocy JavaScript pozwalamy użytkownikom kontrolować, która sekcja jest widoczna. W danym momencie pokazana jest wyłącznie jedna sekcja; aby zobaczyć drugą użytkownik musi aktywować odpowiadający jej link. Właściwie ostylowany, powyższy komponent powinien być dziecinnie prosty do użycia dla osób widzących. Z punktu widzenia osób korzystających z czytników ekranu przedstawia się to jednak zupełnie inaczej.

Powiedzmy, że należymy do tej grupy użytkowników i chcemy zapoznać się z treścią powyższych zakładek. Najpierw natrafiamy na nagłówek “Wydarzenia” – czyli treść poniżej powinna zawierać informację na ich temat. Następnie napotykamy na listę składającą się z dwóch elementów – słowa “Dzisiaj” i linku “Jutro”. To by sugerowało, że wydarzenia na stronie dzielą się na te dwie kategorie. Słowo “Jutro” jest linkiem, zatem oczywiście zakładamy, że jutrzejsze wydarzenia opisane są na oddzielnej stronie, a jako że “Dzisiaj” linkiem nie jest, prawdopodobnie znaczy to, że dzisiejsze wydarzenia opisane są gdzieś poniżej. I rzeczywiście, gdy przechodzimy do dalszej treści napotykamy na sekcję zatytułowaną “Dzisiaj” zawierającą opis dzisiejszych wydarzeń. Póki co wszystko jasne. Ale powiedzmy, że interesują nas także jutrzejsze wydarzenia. Wobec tego wybieramy link “Jutro” i czekamy, aż czytnik ekranu ogłosi, że załadowała się nowa strona, prawdopodobnie zatytułowana “Jutrzejsze wydarzenia” albo podobnie. To jednak nie następuje. Jesteśmy wciąż na tej samej stronie, a czytnik ekranu milczy i nie udziela żadnej informacji o tym, że coś się zmieniło na stronie. Niestety nie jesteśmy świadomi tego, że poniżej wybranego przez nas linku sekcja “Dzisiaj” została ukryta, a na je miejscu wyświetlona jest sekcja “Jutro”. Co się zatem stało? Może link nie zadziałał? Może go jednak nie aktywowaliśmy? Spróbujmy jeszcze raz. Ale stało się coś dziwnego – słowo “Jutro” nie jest już linkiem, tylko zwykłym statycznym tekstem, za to słowo “Dzisiaj” to teraz link. Dlaczego? Wszystko to jest bardzo dezorientujące – osobom korzystającym z czytnika ekranu trudno jest stwierdzić na tym etapie, czy strona działa jak powinna, czy być może wystąpił jakiś błąd. Oczywiście po pewnym czasie (spędzonym na badaniu poszczególnych elementów strony), użytkownicy zorientują się, że wybranie linku z listy powoduje pojawienie się nowej treści na obecnie oglądanej stronie, a nie otwarcie nowej, ale jest to dość dezorientujące i nieintuicyjne rozwiązanie. Z punktu widzenia osób korzystających z czytnika ekranu, jest to bardzo kiepskie UX.

Problem polega na tym, że w HTML nie ma znaczników specjalnie przeznaczonych do oznaczania tego typu zaawansowanych widgetów – nie istnieje element <tabs>, <tabcontrol> czy też <tabpanel>, dlatego nie ma możliwości przekazania za pomocą semantycznego kodu HTML informacji przekazanej wizualnie. Stąd też potrzebne było stworzenie dodatkowej technologii pozwalającej na udostępnienie technologiom asystującym brakujących informacji na temat tego typu skomplikowanych komponentów i ich elementów, umożliwiającej szczegółowe opisanie ich właściwości.

WAI-ARIA

WAI-ARIA (ang. Web Accessibility Initiative – Accessible Rich Internet Applications), to techniczna specyfikacja opublikowana przez W3C, zawierająca zestaw rekomendacji dotyczących poprawy dostępności złożonych aplikacji internetowych. Dokument ARIA stanowi zestaw atrybutów, za pomocą których można nadać semantyczne znaczenie niesemantycznym elementom HTML, bądź też zmienić sematyczne znaczenie elementów, które zostały “przerobione” przy użyciu JavaScript na komponenty służące do innych celów niż jest to opisane w dokumentacji HTML. Dzięki atrybutom ARIA możliwe jest uzupełnienie dostępnościowego drzewka przeglądarki o dodatkowe informacje na temat właściwości tych elementów, a co za tym idzie przekazanie tych informacji technologiom asystującym. Efekty działania atrybutów ARIA są kompletnie niewidoczne dla osób niekorzystających z czytników ekranu – strona, która nie używa ARIA będzie wyglądać dokładnie tak samo, gdy dodamy do niej atrybuty ARIA. Zmieni się za to jej funkcjonalność i użyteczność z punktu widzenia osób korzystających z czytników ekranu.

Rodzaje atrybutów ARIA

Atrybuty ARIA można podzielić na:

Role

Atrybuty z tej kategorii opisują przeznaczenie danego elementu – to, jaką rolę pełni on na stronie. Role ARIA dzielą się na następujące grupy:

  • abstrakcyjne (które nie powinny być używane w treści), np.
    • command
    • section
    • window
  • role widgetów, opisujące przeznaczenie komponentów i ich elementów, np.
    • alert
    • dialog
    • progressbar
    • scrollbar
    • slider
    • spinbutton
    • tab
    • tooltip
    • tree
  • role struktury dokumentu, opisujące strukturę treści przedstawionych na stronie, np.
    • document
    • group
    • presentation
    • toolbar
  • role punktów orientacyjnych (ang. landmarks), opisujące funkcje poszczególnych regionów strony i udostępniające dodatkową metodę nawigacji:
    • application
    • banner
    • complementary
    • contentinfo
    • form
    • main
    • navigation
    • search

Stany i właściwości

Podczas gdy określony element może pełnić wyłącznie jedną rolę, może on posiadać szereg stanów i właściwości, które mogą ulec zmianie w odpowiedzi na działania użytkownika. Można je podzielić na następujące grupy:

  • atrybuty widgetów, np:
    • aria-autocomplete
    • aria-checked
    • aria-disabled
    • aria-expanded
    • aria-hidden
    • aria-label
    • aria-pressed
    • aria-readonly
    • aria-required
    • aria-selected
  • atrybuty regionów, których zawartość jest aktualizowana na żywo (bez odświeżenia strony):
    • aria-atomic
    • aria-busy
    • aria-live
    • aria-relevant
  • atrybuty “drag-and-drop” (przeciągnij i upuść):
    • aria-dropeffect
    • aria-grabbed
  • atrybuty powiązań, opisujące związki pomiędzy elementami strony, które nie mogą zostać przekazane za pomocą struktury dokumentu:
    • aria-activedescendant
    • aria-controls
    • aria-describedby
    • aria-flowto
    • aria-labelledby
    • aria-owns
    • aria-posinset
    • aria-setsize

Przykład – zakładki z ARIA

Spójrzmy jeszcze raz na kod zakładek, tym razem z użyciem odpowiednich ról, stanów i właściwości ARIA:

<h2>Wydarzenia</h2>
<ul role="tablist">
  <li aria-controls="panel1" aria-selected="true" role="tab">Dzisiaj</li>
  <li aria-controls="panel2" aria-selected="false" role="tab">Jutro</li>
</ul>
<section id="panel1" role="tabpanel">
  <h3 class="hidden">Dzisiaj</h3>
  <p>*** Opis dzisiejszych wydarzeń ***</p>
</section>
<!-- poniższa sekcja jest ukryta -->
<section id="panel2" role="tabpanel" style="display: none">
  <h3 class="hidden">Jutro</h3>
  <p>*** Jutrzejsze wydarzenia ***</p>
</section>

(jako że kontrolki w liście zakładek nie są już oznaczone za pomocą elementów interaktywnych (link), trzeba będzie zapewnić dostępność z klawiatury tych elementów w inny sposób – zobacz przykładową implementację)

Lista kontrolek ma teraz zdefiniowaną w kodzie rolę (role="tablist", czyli lista zakładek), a każdy element tej listy został oznaczony jako zakładka (role="tab"). Dzięki dynamicznie zmieniającemu się atrybutowi “aria-selected” możemy określić, która zakładka jest aktualnie wybrana (aria-selected="true"), a która nie (aria-selected="false"), a za pomocą atrybutu “aria-controls” definiujemy w kodzie strony związek pomiędzy zakładką, a kontrolowanym przez nią panelem. Każdy panel ma też przypisaną mu odpowiednią rolę (role="tabpanel").

W tym przypadku osoba korzystająca z czytnika ekranu dowie się dużo więcej na temat prawdziwego działania i właściwości tego komponentu. Jeśli np. użytkownik NVDA przejdzie do pierwszego elementu w liście kontrolek, zostanie powiadomiony, że jest to zakładka “Dzisiaj”, jedna z dwóch, i że jest ona aktualnie wybrana.

Więcej na temat ARIA

Dodaj komentarz

Należy wypełnić wszystkie pola oznaczone asteryskiem (*).
Zanim komentarz zostanie opublikowany będzie musiał zostać zatwierdzony przez moderatora.

Możesz wykorzystać następujące elementy HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>