Szaktanácsadás akadálymentes honlap készítéséhez

Élő régiók definiálása aria-live attribútummal

Mi a kiindulási akadály?

A képernyőolvasós böngészésnek van egy olyan jellegzetessége, hogy a képernyőolvasó program egyszerre csak a weboldal egy adott elemére fókuszál. Így ha időközben valami megváltozik a weboldal egyéb területén (például megjelenik egy hibaüzenet), akkor ezt a változást a vak felhasználók nagy valószínűséggel nem veszik észre. Főleg akkor nem, ha a változás az oldal azon részén történik, amin már áthaladtak.

A képernyőnagyító programot használó gyengénlátó felhasználók számára is általában az egyik legnagyobb probléma, amikor a változás az oldal azon részén történik, ami pont kívül esik az éppen kinagyított képernyőrészletből. Ezen részben olyan tudatos tervezés segíthet, ami például a felhasználó által végrehajtott művelet eredményét vizuálisan minél közelebb jeleníti meg ahhoz az elemhez, ahonnan a műveletet elindította. De mivel a gyengénlátó felhasználók közül többen képernyőolvasós támogatást is használnak a képernyőnagyítás mellé, így a cikkben tárgyalt aria-live nekik is segítséget jelenthet.

Gyorsan hozzáteszem, hogy a látó felhasználók számára sem mindig evidens olyan megjelenést készíteni, hogy a változást valóban észrevegyék, de azért a vizuális tervezés számtalan bevált módszert ismer erre a problémára.

Mit jelent az, hogy élő régió?

Az aria-live attribútum segítségével úgynevezett élő régiókat definiálhatunk a weboldalunkon, vagy a webalkalmazásunkban.

Egy ilyen régiót két okból nevezünk élőnek. Egyrészt feltételezzük, hogy a régió tartalma az oldal újratöltése nélkül, valamilyen külső esemény (pl. AJAX válasz), vagy a felhasználó által végzett interakció hatására folyamatosan változni fog. Másrészt azt szeretnénk, hogy ezekről a változásokról a képernyőolvasós felhasználó akkor is értesüljön, ha éppen az oldal egy másik részén tartózkodik.

Az aria-live attribútumot elvben bármelyik HTML jelölőelem megkaphatja. A hétköznapi gyakorlatban legtöbbször div, span, vagy p jelölőelemnél használjuk, hiszen ezek kellően semleges elemek az élő régiók definiálására. De előfordulhat, hogy egy ul vagy ol listát is élőnek definiálunk.

A következő példában egy div jelölőelem által meghatározott régiót teszünk élővé:

<div id="statusz" aria-live="polite">

<!-- ide jön majd a dinamikusan frissülő tartalom -->

</div>

Innentől kezdve a képernyőolvasó program „figyeli” a régiót, és ha JavaScript segítségével DOM manipulációt (pl. beszúrást, változtatást, törlést, stb.) végzünk benne, akkor ezt változásnak minősíti. Az már a régió egyéb aria- tulajdonságaitól is függ, hogy mikor és melyik változást közli majd a képernyőolvasós felhasználóval.

Tipikus példa a változtatásra, hogy az élő régióba egy szöveges üzenetet helyezünk el, amit valószínű, hogy egy látó felhasználó azonnal észrevesz (mert például feltűnő a régió megjelenése), de azt is szeretnénk, hogy a képernyőolvasós felhasználóhoz is mihamarabb eljusson:

document.getElementById('statusz').textContent = 'A keresési feltételeknek 15 szálláshely felelt meg.';

Mikor kerül felolvasásra?

Ezt a kérdést az aria-live attribútum aktuális értéke dönti el, amit egyfajta sürgősségi szintként is értelmezhetünk.

aria-live="off"

<div id="statusz" aria-live="off">

<!-- ide jön majd a dinamikusan frissülő tartalom -->

</div>

Ebben az esetben a régióban történő változást nem fogja beolvasni a képernyőolvasó program, hacsak éppen nem ez a régió van a felhasználó fókuszában. Így ezt a régiót olyan információk közlésére használhatjuk, amelyeket nem szükséges azonnal átadnunk a felhasználó számára.

Ugyanakkor az off érték arra is alkalmas, hogy egy már élő régió „élőségét” ideiglenesen, vagy véglegesen kikapcsoljuk.

aria-live="polite"

<div id="statusz" aria-live="polite">

<!-- ide jön majd a dinamikusan frissülő tartalom -->

</div>

Ezt az értéket akkor használjuk, ha az élő régióban történt változás ugyan fontos, de nem annyira, hogy erről azonnal értesüljön a felhasználó. A képernyőolvasó program ilyenkor udvariasan megvárja azt az alkalmat, amikor legkevésbé „zavarja” a felhasználót, és közölheti vele a változást. Például ilyen időpillanat lehet az, amikor a felhasználó éppen nem gépel, vagy befejezte az oldal valamely részének felolvastatását.

A polite értesítési szintű élő régió tipikusan státuszüzenetek, illetve kisebb figyelmeztető üzenetek közlésére alkalmas.

aria-live="assertive"

<div id="statusz" aria-live="assertive">

<!-- ide jön majd a dinamikusan frissülő tartalom -->

</div>

Az ilyen jellegű régióban bekövetkező változás annyira fontos, hogy a felhasználót azonnal értesíteni kell róla. A képernyőolvasó program ilyenkor nem udvariaskodik, hanem a lehető leghamarabb beolvassa a változást, még akkor is, ha ezzel esetleg megszakítja az éppen zajló felolvasást. Mivel ez a megszakítás jelentősen megzavarhatja a felhasználói élményt, ezért nagyon fontos, hogy assertive jellegű régiót tényleg csak akkor használjunk, ha az azonnali értesítés a felhasználó érdekeit szolgálja. Első lépésben mindig a polite használatában gondolkozzunk, és csak alapos mérlegelés után döntsünk az assertive mellett.

Az assertive értesítési szintű élő régió tipikusan hibaüzenetek, illetve kritikus státuszüzenetek közlésére alkalmas.

Hibaüzenetes példa

Űrlapoknál nagyon gyakran használják azt módszert, hogy ha a felhasználó továbblép (kilép) egy hibásan kitöltött űrlapmezőből, akkor a hibajelzés rögtön megjelenik a mező mellett.

Az alábbi példa egy ilyen szituációt mutat. Feltételezzük, hogy a felhasználó már átlépett a név mezőből a jelszó mezőbe, és a név mezőnél megjelent egy hibaüzenet (aminek szövegét JavaScript segítségével szúrtuk be):

<label for="nev">Név</label>
<input id="nev" type="text">
<span id="nev-hibauzenet">Kérjük, a névhez legfeljebb 10 karaktert írjon.</span>

<label for="jelszo">Jelszó</label>
<input id="jelszo" type="password"> <!-- jelenleg itt van a fókusz -->
<span id="jelszo-hibauzenet"></span>

Egy látó felhasználó azonnal észreveszi a név mezőnél megjelenő hibaüzenetet, tehát könnyen visszalép a hibás mezőbe, és korrigálja a hibáját. De egy vak felhasználó nem veszi észre a hibaüzenetet, hiszen ő már a jelszó mezőben van, tehát már a képernyőolvasó program is ennek a mezőnek az adatait olvassa fel neki.

Sajnos a fenti példa már abból a szempontból sem akadálymentes, hogy ha véletlenül mégis visszalépne a név mezőbe, akkor sem hallaná, hogy a mező hibás, és azt sem, hogy pontosan mi a hiba. Első lépésben ezt a problémát korrigáljuk.

Két aria- attribútumot hívunk segítségül. Az aria-invalid="true" attribútummal jelezzük, hogy a mező jelenleg hibás. Az aria-describedby attribútummal pedig logikailag összekapcsoljuk a hibás mezőt a hibaüzenettel (hasonlóan ahhoz, ahogy egy korábbi cikkemben a súgószöveget kapcsoltuk össze a mezővel). Az eredmény az lesz, hogy ha a felhasználó a név mezőben van, akkor a képernyőolvasó program jelzi neki, hogy a mező hibás, és felolvassa a hibaüzenetet is.

<label for="nev">Név</label>
<input id="nev" type="text" aria-invalid="true" aria-describedby="nev-hibauzenet">
<span id="nev-hibauzenet">Kérjük, a névhez legfeljebb 10 karaktert írjon.</span>

Hangsúlyoznám, hogy a hibaüzenet megjelenítésekor az aria-invalid tulajdonságot JavaScript segítségével állítjuk be. Az aria-describedby már benne lehet az oldal kiindulási HTML kódjában, de ha kell, akkor JavaScript-ből is beállítható.

De most térjünk vissza a kiindulási problémához, vagyis ahhoz, hogy a felhasználó már régen a jelszó mezőben van, de nem értesült arról, hogy a név mezőnél egy hibaüzenet jelent meg.

A megoldás az lehet, hogy a hibaüzenetet tartalmazó elemet élő régióként definiáljuk. Mivel felhasználói beavatkozást igénylő, fontos dologról van szó, ezért jelen esetben az assertive értesítési szint (tehát az azonnali értesítés) teljesen jogos.

<label for="nev">Név</label>
<input id="nev" type="text" aria-invalid="true" aria-describedby="nev-hibauzenet">
<span id="nev-hibauzenet" aria-live="assertive">Kérjük, a névhez legfeljebb 10 karaktert írjon.</span>

<label for="jelszo">Jelszó</label>
<input id="jelszo" type="password" aria-describedby="jelszo-hibauzenet"> <!-- jelenleg itt van a fókusz -->
<span id="jelszo-hibauzenet" aria-live="assertive"></span>

Az élő régiókat nyugodtan definiálhatjuk már az oldal kiindulási HTML kódjában is. A fenti példában a jelszó mező hibaüzenetének régiója is élő, pedig abban aktuálisan nincs hibaüzenet.

Ezzel tehát elértük azt, hogy ha a képernyőolvasós felhasználó rosszul tölti ki a név mezőt, majd továbblép a jelszó mezőbe, akkor azonnal hallja, hogy a név mezőnél valamilyen hiba lépett fel. Ha rögtön ezután, vagy esetleg a további mezők kitöltése után visszalép a név mezőbe, akkor egyértelműen hallja, hogy hibás a mező, és azt is, hogy mi a hibaüzenet.

Demó

Az alábbi videóban megnézhető, illetve meghallgatható a példánk kiindulási (vagyis az aria-live nélküli), illetve az aria-live segítségével elkészített verziója is.

A videón a két űrlapmező látszik egymás alatt, és amikor a kitöltött név mezőből átlépünk a jelszó mezőbe, akkor a név mező mellett megjelenik a hibaüzenet. A demonstrációhoz a macOS operációs rendszeren futó VoiceOver képernyőolvasót használtam Safari böngészőben.

A demó egyébként élőben is kipróbálható.

aria-atomic attribútum

Vannak olyan esetek, amikor nem változtatjuk meg az élő régió teljes tartalmát, hanem csak egy részét.

Vegyünk példának egy webáruházat. Amikor a felhasználó beteszi a kiválasztott terméket a kosarába, akkor a kosárban lévő termékek darabszámát jelző régió azonnal frissül. Természetesen azt szeretnénk, hogy a darabszám változásáról minden felhasználó értesüljön, még akkor is, ha a kosárba helyező gomb, és a kosarat reprezentáló régió a weboldalon esetleg egymástól távol van.

Adódik tehát, hogy élő régiónak definiáljuk a kosár régióját. Itt is az assertive értesítési szintet használjuk, mert így azonnali visszajelzést adhatunk a felhasználónak a gomb megnyomását követő akció sikerességéről is.

<p aria-live="assertive">A kosarában jelenleg <span id="darabszam">2</span> termék van.</p>

Amikor a felhasználó betesz egy új terméket a kosarába, akkor az oldal JavaScript kódja vélhetően csak a darabszámot kiíró span elem tartalmát fogja megváltoztatni. Például így:

document.getElementById('darabszam').textContent = darabszam++; 

Azt várnánk, hogy ilyenkor a képernyőolvasó program azonnal azt olvassa fel, hogy A kosarában jelenleg 3 termék van.. Ehelyett csak annyit fog a felhasználó hallani, hogy 3, ami nem túl értelmes információ.

Ennek oka, hogy a WAI-ARIA szabvány szerint a képernyőolvasó programnak alapértelmezetten csak az élő régió azon részét kell felolvasnia, ami megváltozott.

Ha azt szeretnénk, hogy minden esetben elhangozzon a régió teljes tartalma, akkor a régió aria-atomic attribútumát true értékre kell állítanunk (alapértelmezetten ez false):

<p aria-live="assertive" aria-atomic="true">A kosarában jelenleg <span id="darabszam">2</span> termék van.</p>

Természetesen vannak olyan feladatok, amikor pont az alapértelmezett érték, vagyis az aria-atomic="false" a megfelelő. Gondoljunk például egy chat alkalmazásra, ahol nagyon idegesítő lenne, ha képernyőolvasó nem csak a chat élő régiójában megjelenő új hozzászólást olvasná fel, hanem a chat teljes addigi tartalmát is.

aria-relevant attribútum

Már említettem, hogy az élő régióban lévő összes DOM manipuláció változásnak minősül. Mégis az esetek túlnyomó többségében csak az érdekel minket (illetve a felhasználót), ha az élő régióba új elem kerül be, vagy a meglévő szövege megváltozik. Nem véletlen, hogy a WAI-ARIA szabvány szerint a képernyőolvasó programnak alapértelmezetten csak ezeket kell felolvasnia.

Nagyon kivételes esetben azonban előfordulhat, hogy az élő régióból történő törlésről is értesülnie kell a felhasználónak, vagy valami egyéb kombinációt kell figyelni.

Az aria-relevant attribútumban megadható, hogy melyik változást, illetve változásokat tekintse relevánsnak a képernyőolvasó program. Az attribútumba szóközzel elválasztva egy vagy több érték is beírható az alábbiak közül:

  • additions (az új elemek beillesztése releváns)
  • text (a meglévő elemek szöveges tartalmának megváltoztatása releváns)
  • removals (a meglévő elemek törlése releváns)

Az élő régiók alapértelmezetten aria-relevant="additions text" tulajdonsággal rendelkeznek, tehát ha ez a kombináció nekünk is megfelel (márpedig általában megfelel), akkor az aria-relevant attribútumot nem szükséges külön megadnunk.

Van egy speciális értéke is az attribútumnak. Az aria-relevant="all" azt jelenti, hogy az összes felsorolt változás releváns.

Hasznos tanácsok az aria-live használatához

Saját tapasztalataim alapján összegyűjtöttem néhány tippet, ami az élő régiókkal kapcsolatos.

Csak röviden!

Mindig olyan aria-live régiót tervezzünk, ami nem fog feleslegesen, vagy értelmetlenül sok információt közölni a felhasználóval. Törekedjünk a tömör, világos, és informatív fogalmazásra.

Akadálymentességi tanácsadóként már találkoztam olyan esettel, amikor a fejlesztők úgy gondolták, hogy egy dinamikusan megjelenő űrlapszakaszra, vagy egy kalkuláció eredményeképp megjelenő komplex táblázatra teszik rá az aria-live-ot. Mondanom sem kell, hogy ennek így nincs értelme. Egyszerűbb, ha például a kalkuláció végén, az eredménytáblázat megjelenésekor csak egy rövid státuszüzenet lesz élő régióban, ami jelzi, hogy megjelent az eredmény. Ha a táblázat logikusan van elhelyezve, akkor a képernyőolvasós felhasználó magától is megtalálja majd azt, és csak annyit olvastat fel belőle, amennyit szeretne.

Nem kell mindig látszódnia

Könnyű helyzetben vagyunk, ha élő régiónak definiálhatunk egy vizuálisan is látszódó elemet. Így tettünk a hibaüzenetes példánál is, hiszen egy látható hibaüzenetet tettünk hallhatóvá.

De nagyon sokszor hozunk létre olyan élő régiókat, amelyek vizuálisan nem jelennek meg. Ezeket a vizuálisan rejtett élő régiókat kizárólag a vak felhasználóknak szánjuk, hiszen számos (a látók számára evidens) változást csak velük kell ilyen direkt módon közölni.

Fontos, hogy a vizuálisan rejtett élő régiót semmiképpen se a display:none CSS szabállyal rejtsük el, hanem a rejtésekkel foglalkozó cikkemben leírt módszert használjuk.

Tipikus példa egy olyan kereső, ahol a keresendő szó beírásával párhuzamosan egy választólista is megjelenik a releváns keresőszavakkal. Egy látó felhasználó ezt a listát rögtön észreveszi, és azt is érzékeli, hogy kb. hány keresőszó jelent meg benne. Egy vak felhasználó azonban egyiket sem veszi észre. Ilyenkor segíthet egy olyan polite jellegű, vizuálisan rejtett élő régió, amiben például a megjelent keresőszavak számát közöljük. Mondjuk így: 9 találat jelent meg. (Megjegyzem, semmi nem zárja ki, hogy ez az üzenet akár vizuálisan is megjelenjen, hiszen például a képernyőnagyítós felhasználóknak is segíthet. Döntés kérdése, hogy rejtett legyen, vagy látszódjon.)

Bevált gyakorlat az is, amikor a HTML kódban legalul (valahol a záró body elem előtt) állandóra elhelyezünk egy polite jellegű, vizuálisan rejtett élő régiót, amit aztán a különböző státuszüzenetek közlésére használhatunk. Néhány éve például a WordPress tartalomkezelő rendszer is ezt a módszert alkalmazza. A WordPress-ben a wp.a11y.speak() függvény segítségével bármikor üzenetet tehetünk ebbe a régióba, hogy a képernyőolvasó programok felolvashassák.

Tesztelés, tesztelés, tesztelés

Mivel az aria-live nem egy túlságosan régi és kiforrott technológia, ezért a gyakorlati működése során még érhetnek minket meglepetések. Mindig le kell tesztelni, hogy a tervezett megoldás vajon tényleg működik-e a különböző operációs rendszerek különböző képernyőolvasó programjaiban.