Aria oferuje 3 podstawowe elementy ułatwiające komunikację programu czytającego z przeglądarką.
Role (Roles)
Role przekazują informacje do aplikacji asystujących, że opisany nimi element jest czymś innym niż wynika to z jego znacznika. Większość znaczników HTML posiada swoją domyślną rolę i dzięki temu są osiągalne np. dla programów czytających poprzez skróty klawiaturowe opisane w poprzednim artykule „ARIA, wszędzie ARIA – wstęp„. Przykładem może być znacznik <h1>
, który pełni rolę nagłówka pierwszego poziomu. Znacznik <button>
pełni rolę przycisku, a znacznik <a href="">
pełni rolę odnośnika. Na tym polega właśnie ich semantyka.
Role mogą również nadawać znaczenia, których w HTML nie ma jak np.: ostrzeżenie, okienko dialogowe, zakładki, pasek postępu, suwak, itp.
Wyjątkiem są landmarki, które nie zmieniają znaczenia elementu HTML, lecz dodatkowo określają jaką jest częścią dokumentu np. nawigacją, wyszukiwarką, artykułem, stopką, itp., ale o tym później bo … teraz zaczyna się najlepsza zabawa :).
Skoro możemy zmieniać dowolnie role znaczników, to po co nam teraz semantyczne znaczniki HTML? Zamiast <button>wyślij</button>
w formularzu możemy osadzić <span role="button">wyślij</span>
. Oba są teraz przyciskami. Jest jednak podstawowa różnica. Pierwszy jest przyciskiem w pełnym tego słowa znaczeniu, a to oznacza, że będzie osiągalny za pomocą klawiatury, uzyska fokus i wyśle formularz. Drugi przykład powie jedynie przeglądarce, że ma anonsować tekst „Wyślij” jako przycisk i nic więcej. Nie będzie osiągalny z klawiatury, nie otrzyma fokusa i nie wyśle formularza. Fokusa otrzyma jedynie wtedy kiedy dodamy do niego dodatkowo atrybut tabindex="0"
. Formularz zostanie wysłany tylko wtedy, kiedy oprogramujemy takie zdarzenie w JavaScript.
Wnioski z podanego powyżej przykładu dowodzą, że stosowanie semantycznych znaczników HTML jest o wiele szybsze, bezpieczniejsze i nie wymaga znajomości JavaScript.
W podanym przykładzie była próba nadania znaczenia dla niesemantycznego elementu <span>
. Gorzej jednak, kiedy wykonawca zmienia natywną rolę znacznika HTML.
Podczas jednego z badań dostępności okazało się, że większość odnośników na stronie głównej pewnego serwisu posiadało rolę przycisku (<a href="" role="button" >
). Poruszając się po nich programem czytającym użytkownik zamiast słyszeć „link” otrzymywał informację, że jest to „przycisk”. Cała strona sprawiała wrażenie jednego wielkiego formularza z mnóstwem przycisków wprowadzając użytkownika w błąd i dezorientację.
Powyższe przykłady pokazują jak wiele zagrożeń podczas budowy serwisu czyha na webdeveloperów i programistów. Tak, napisałem „programistów”, bo to oni głównie tworzą frameworki, gotowe biblioteki, które później niczego nie świadomi webdeveloperzy wykorzystują w swoich serwisach.
Właściwości (Properties)
Właściwości ARIA określają cechy lub dodatkowe znaczenie danego elementu, które nie są dostępne w standardzie HTML. Wszystkie właściwości i statusy ARIA zaczynają się od prefiksu aria-
. Najlepiej pokazać to na przykładzie:
<label for="telefon">Numer telefonu</label>
<input type="text" name="telefon" id="telefon" aria-required="true" aria-describedby="tel_info">
<p id="tel_info">Numer telefonu nie może zawierać spacji i myślników</p>
Atrybut aria-required
z wartością ustawioną na true
informuje aplikacje asystujące, że pole jest wymagane.
Kolejny atrybut aria-describedby
informuje aplikacje asystujące, że pole tekstowe jest dodatkowo opisane przez element o identyfikatorze tel_info
. Efekt będzie taki, że nawigując programem czytającym oprócz etykiety „Numer telefonu” program odczyta również dołączoną informację „Numer telefonu nie może zawierać spacji i myślników” oraz, że jest to pole wymagane.
Statusy (States)
Statusy pozwalają określić jaki jest aktualny stan elementu. W dużej części przypadków są one dynamicznie zmieniane np. za pomocą JavaScript. Najprostszym przykładem może być atrybut aria-expanded
, który przyjmuje dwie wartości: true
jeśli jest rozwinięty oraz false
kiedy jest zwinięty.
Innym prostym przykładem jest atrybut aria-hidden
, który również przyjmuje dwie wartości: true
i false
. Oznacza on, czy aplikacja asystująca ma dany element pominąć i go nie przetwarzać.
Zapamiętaj
Jeśli budujesz serwis za pomocą gotowych bibliotek, wykorzystujesz frameworki, zanim wybierzesz konkretne rozwiązanie przetestuj je programem czytającym oraz sprawdź nawigację bez użycia myszki, tylko za pomocą klawiatury. Nawet jeśli autor zapewnia zgodność ze standardem WCAG oraz wsparcie ARIA.
Kieruj się podstawową zasadą (Using ARIA in HTML):
If you can use a native HTML element [HTML5] or attribute with the semantics and behaviour you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so.
Najprościej ujmując oznacza to, że jeśli to możliwe używaj natywnych semantycznych znaczników HTML zamiast stosowania roli i atrybutów ARIA.
A jak zrobić, by np zakładka (tab) zmieniała dynamicznie oznajmianie tj. jeśli jest zwinięta to: aria-expanded=”false a gdy rozwinięta to: aria-expanded=”true”? Chodzi o to, by czytnik informował, że w zależności od pozycji, podawana była właściwa informacja.
Atrybut
aria-expanded
można stosować raczej do konstrukcji o funkcjonalności akordeonów. Dla zakładek należy użyćaria-selected
jak na przykładzie poniżej.<ul role="tablist">
<li role="presentation"><a href="#tab1" tabindex="0" role="tab" aria-controls="tab1" aria-selected="true">Zakładka 1</a></li>
<li role="presentation"><a href="#tab2" tabindex="-1" role="tab" aria-controls="tab2">Zakładka 2</a></li>
<li role="presentation"><a href="#tab3" tabindex="-1" role="tab" aria-controls="tab3">Zakładka 3</a></li>
</ul>
<section id="tab1" role="tabpanel">
...
</section>
<section id="tab2" role="tabpanel" aria-hidden="true">
...
</section>
<section id="tab3" role="tabpanel" aria-hidden="true">
...
</section>