Hogyan adjunk akadálymentes nevet?

A cikk témái

A weboldal számos elemének – különösképpen az interaktív komponenseknek – nevet kell adnunk. A név alapvetően arra szolgál, hogy egy rövid és érthető információt nyújtson az adott komponens céljáról, valamint egyértelműen beazonosíthatóvá tegye azt.

E két tényező elsősorban azon felhasználóinknak fontos, akik valamilyen speciális kisegítő eszközzel (például képernyőolvasó programmal vagy hangvezérléssel) böngészik az oldalunkat.

Ha például egy vak felhasználó ránavigál egy komponensre, akkor a képernyőolvasó program a komponens típusa (szerepe) mellett a komponens nevét is beolvassa. Vagy ha egy mozgássérült felhasználó a beszédfelismerő eszközének kimondja a komponens nevét, akkor az eszköz a név alapján már képes beazonosítani, és kérésre akár aktiválni is a kiválasztott komponenst.

A név definiálása nem teljesen triviális. Legalábbis abban az értelemben nem, hogy a HTML-ben nincs csak egy, kifejezetten erre a célra dedikált attribútum. Ugyan létezik a name attribútum, de ez abszolút más célokat szolgál.

Alapszabályként lefektethetjük, hogy a legegyszerűbb esetekben a komponens neve elvileg ugyanaz lesz, mint a komponens vizuálisan is látható címkéje (szövege). Például egy szöveges gombnál a gomb felirata (mondjuk a „Kiszámolom” szöveg) egyben a gomb neve is lehet. Vagy egy űrlapmezőnél a logikailag hozzákapcsolt <label> címke szövege biztosíthatja a nevet.

Ugyanakkor a név sok esetben a komponens egy láthatatlan tulajdonságából is származhat. Gondoljuk például egy olyan gombra, amin csak egy ikon látszik. Ilyenkor a fejlesztő döntésétől függ, hogy az ikon szöveges alternatívájával, a gomb vizuálisan rejtett, de képernyőolvasóval elérhető szövegével, vagy esetleg a gomb <button> jelölőelemének valamelyik attribútumával szeretné definiálni a gomb nevét.

Az mindig a komponens pontos típusától függ, hogy mely HTML attribútumok definiálhatják a nevét. Így például a title, a value, vagy az alt attribútumok is szóba jöhetnek, amennyiben a HTML szabvány megengedi ezen attribútumok használatát az adott jelölőelemnél. De az WAI-ARIA szabványban definiált aria-label, illetve aria-labelledby tulajdonságokkal (attribútumokkal) is operálhatunk. Ráadásul ezeket kötöttség nélkül, bármely HTML jelölőelemnél használhatjuk.

A névkalkulációs algoritmus

Fontos azonban tudni, hogy az említett lehetőségekkel csak potenciális „névjelölteket” definiálunk.

A komponens tényleges nevét ugyanis a böngészőprogram egy vagy több ilyen potenciális névjelöltből kalkulálja ki, majd a kikalkulált nevet eltárolja az úgynevezett akadálymentességi fában (angolul accessibility tree). Az akadálymentességi fára ebben a cikkemben nem szeretnék részletesen kitérni. Most csak annyit jegyeznék meg róla, hogy ez az az objektumstruktúra, amit a böngészőprogramok a különböző kisegítő eszközök kiszolgálására állítanak össze. Ezek az eszközök ugyanis elsődlegesen nem a HTML kódból vagy a DOM fából, hanem a böngészőprogram által legenerált akadálymentességi fából olvassák ki a weboldal objektumaira vonatkozó információkat. Például ebből szerzik meg a képernyőolvasó programok is a weboldal komponenseinek nevét.

Szerencsére a böngészőprogramok által alkalmazott névkalkulációs algoritmus ma már jól specifikált. Az Accessible Name and Description Computation, illetve a HTML Accessibility API Mappings című W3C specifikációk részletesen leírják az algoritmus lépéseit, így egyre kisebb lesz az esélye annak, hogy az egyes böngészőprogramok különböző nevet kalkulálnának az adott komponenshez.

Ugyan az említett specifikációk alapvetően a böngészőgyártók számára készültek, de nekünk is érdemes tisztában lennünk a névkalkulációs algoritmus alapjaival. Főleg azért, mert ha a fejlesztés során – szándékosan vagy véletlenül – több névjelöltet is definiálunk ugyanahhoz a komponenshez, akkor nem árt tudni, hogy ezekből melyik kerül ki majd győztesen, azaz melyik lesz a komponens tényleges neve.

A névkalkuláció algoritmusa egy szigorú sorrendiségen alapszik. A böngészőprogram egy előre meghatározott sorrendben megnézi, hogy a potenciális névjelöltek közül melyik definiált és érvényes. Az első megfelelő jelölt lesz a tényleges név, a többi nem játszik. Ha a böngészőprogram nem talál használható névjelöltet, akkor a komponensnek nem lesz neve.

A névjelöltek erősorrendje nagyon vázlatosan így néz ki:

  1. aria-labelledby attribútum
  2. aria-label attribútum
  3. az adott komponens jelölőeleméhez engedélyezett speciális attribútum (pl. alt, value), vagy a logikailag hozzákapcsolt címke (pl. <label>, <caption>, stb.)
  4. az adott komponens szöveges tartalma (ha a komponensnek lehet ilyenje)
  5. title attribútum

Vegyünk egy eléggé életszerűtlen, de annál szemléletesebb példát. Legyen a komponensünk egy gomb, amit az alábbi kóddal definiálunk:

<button aria-label="Az aria-label nyert" title="A title nyert">A szöveges tartalom nyert</button>

Természetesen vizuálisan egy olyan gomb fog megjelenni, aminek felirata A szöveges tartalom nyert szöveg lesz. Elvileg ez a szöveges tartalom is egy lehetséges névjelölt. De mivel a gomb aria-label és title attribútuma is definiálva van, és mindkettő a specifikációnak megfelelően érvényes, ezért a fenti erősorrendből adódóan az aria-label fog nyerni, vagyis ez adja a nevet. Ezért például a képernyőolvasó program is így fogja felolvasni a komponenst:

Gomb, Az aria-label nyert

Megjegyzés: nagyon fontos, hogy a komponens nevébe soha nem kell beleírni, hogy az milyen elem (például egy gomb). Ez az információ ugyanis a komponenst definiáló HTML jelölőelem szemantikájából, vagy ennek hiányában a role attribútumának értékéből jön. Példánkban a <button> jelölőelem miatt olvassa fel a képernyőolvasó, hogy Gomb.

A névkalkuláció monitorozása

A Chrome böngésző fejlesztői eszköztárában van egy nagyon jó névkalkulációs monitorozóeszköz, ami az Accessibility fül Computed Properties lenyílójában található.

Képernyőfotó egy kinyitott fejlesztői eszköztárral rendelkező Chrome
böngészőablakról, amiben a példánk HTML kódja, a névkalkulációs
monitorozóeszköz, és legenerált weboldal látszik.
A Chrome fejlesztői eszköztárának névkalkulációs monitora

Ahogyan a fenti képernyőképen is látszik, a Name tulajdonság mindig megmutatja a kijelölt komponens kikalkulált nevét (példánknál Az aria-label nyert szöveget), és a kalkulációhoz felhasznált összes névjelöltet. Utóbbiaknál azt is megmutatja, hogy melyek nem voltak megadva (Not specified), és áthúzással jelöli azokat, amelyek kiestek a kalkulációból. Esetünkben Not specified értékű az aria-labelledby és a From label (vagyis a logikailag hozzákapcsolt <label> elemből származó) névjelölt. Míg A szöveges tartalom nyert szövegű Contents (vagyis a szöveges tartalom) és A title nyert értékű title attribútum át van húzva.

A képen az is jól látszik, hogy a weboldalon A szöveges tartalom nyert feliratú gomb jelenik meg. Tehát a gomb felirata és a neve teljesen eltér egymástól, ami nem helyes. De erről majd később.

Adjunk értelmes nevet a Tovább… linkeknek

Nézzünk most egy olyan példát, ami életszerűbben mutatja a névkalkuláció előnyeit. Tételezzük fel egy olyan kódrészletet, amiben egy hír címe, bevezetője, és a hírre mutató Tovább olvasom szövegű link található.

<h2>Átadásra került Budapest 15. mentőállomása a Szent Márton Gyermekmentő Szolgálat jóvoltából</h2>
<p>A Szent Márton Gyermekmentő Szolgálat még többet szeretne tenni a hazai sürgősségi gyermekmentés ügyéért, ezért vásárolt és felújított egy ingatlant, amely a Gyermekrohamkocsinak új „otthont” ad, a gyermekmentésnek egy oktatási központot biztosít, továbbá bővíti az Országos Mentőszolgálat budapesti mentőállomásainak hálózatát.</p>
<p><a href="mentoallomas.html">Tovább olvasom</a></p>

A kódban található három elem közül most koncentráljunk a linkre, vagyis az <a> elemre.

Mivel ennek a linknek most csak egy névjelöltje van (maga a link szövege), így a kikalkulált neve is a Tovább olvasom lesz. Ez annyiból nem szerencsés, hogy önmagából ebből a névből nem derül ki, hogy pontosan melyik hírt tudja majd elolvasni a képernyőolvasós felhasználó, ha aktiválja a linket. A WCAG akadálymentességi szabvány 2.4.4-es alapkövetelménye is előírja, hogy a link szövege lehetőleg önmagában is ismertesse a link célját. A képernyőolvasó program ugyanis most valami ilyesmit fog neki felolvasni, ha rálép a linkre:

Link, Tovább olvasom

A problémát több módon is orvosolhatjuk.

Az egyik lehetőség, hogy egy vizuálisan rejtett, de képernyőolvasóval elérhető szövegrészletet illesztünk a link végére, így a link képernyőolvasós neve a Tovább olvasom szöveg mellett (után) tartalmazni fogja a hír címét is:

<a href="mentoallomas.html">Tovább olvasom <span class="vizualisrejtes">Átadásra került Budapest 15. mentőállomása a Szent Márton Gyermekmentő Szolgálat jóvoltából</span></a>

Így a képernyőolvasó program ezt fogja felolvasni, ha a felhasználó rálép a linkre:

Link, Tovább olvasom Átadásra került Budapest 15. mentőállomása a Szent Márton Gyermekmentő Szolgálat jóvoltából

Az aria-label alkalmazása

Egy másik megoldás lehet az, ha a linknek a szöveges tartalmánál erősebb névjelöltet definiálunk, mondjuk az aria-label attribútumon keresztül. Ilyenkor akár még egy szebb, kerekebb nevet is megfogalmazhatunk:

<a href="mentoallomas.html" aria-label="Tovább olvasom az Átadásra került Budapest 15. mentőállomása a Szent Márton Gyermekmentő Szolgálat jóvoltából című hírt">Tovább olvasom</a>

Fontos, hogy változatlanul Tovább olvasom lesz a link látható szövege, csak a neve lesz bővebb szövegű. Egy képernyőolvasó jellemzően így fogja felolvasni:

Link, Tovább olvasom az Átadásra került Budapest 15. mentőállomása a Szent Márton Gyermekmentő Szolgálat jóvoltából című hírt

További megoldás lehet, ha a legerősebb névjelöltet, vagyis az aria-labelledby attribútumot vetjük be.

Az aria-labelledby alkalmazása

Az aria-labelledby attribútum lényege, hogy a komponens nevét id értékkel azonosított komponens (vagy komponensek) kikalkulált nevéből „szedjük össze”.

Ha csak egy id értéket adunk meg, akkor a komponens neve az adott id értékkel azonosított komponens kikalkulált neve lesz.

Ha szóközökkel elválasztva több id értéket sorolunk fel, akkor a komponens neve a felsorolt id értékekkel azonosított komponensek kikalkulált neve lesz, mégpedig a felsorolás sorrendjében.

Érdekesség, hogy egy komponens visszahivatkozhat a saját id értékére is, de a névkalkulációs algoritmus specifikációja alapján ez nem fog végtelen rekurziót eredményezni.

Tegyünk néhány id attribútumot a példakódunkba, hogy az aria-labelledby bevethető legyen. Adjunk egy id attribútumot a <h2> címsornak, és egyet a linknek is:

<h2 id="hir-1-cim">Átadásra került Budapest 15. mentőállomása a Szent Márton Gyermekmentő Szolgálat jóvoltából</h2>
<p>A Szent Márton Gyermekmentő Szolgálat még többet szeretne tenni a hazai sürgősségi gyermekmentés ügyéért, ezért vásárolt és felújított egy ingatlant, amely a Gyermekrohamkocsinak új „otthont” ad, a gyermekmentésnek egy oktatási központot biztosít, továbbá bővíti az Országos Mentőszolgálat budapesti mentőállomásainak hálózatát.</p>
<p><a href="mentoallomas.html" id="hir-1-link">Tovább olvasom</a></p>

Megjegyzés: Azért használok számozást az id értékekben, mert feltételezhetően több hír is lesz az oldalon, és az id értékeknek muszáj teljesen egyedieknek lenniük. Sajnos az akadálymentességi auditok során sok olyan weboldallal találkoztam, ahol az id értékek nem volt egyediek, így bizonyos komponensek teljesen rossz nevet kaptak.

Most már definiálhatunk egy aria-labelledby attribútumot a linknek, amiben először a link saját id értékét, majd a hírcím id értékét soroljuk fel:

<a href="mentoallomas.html" id="hir-1-link" aria-labelledby="hir-1-link hir-1-cim">Tovább olvasom</a>

Így a link kikalkulált neve az lesz, hogy Tovább olvasom Átadásra került Budapest 15. mentőállomása a Szent Márton Gyermekmentő Szolgálat jóvoltából. Természetesen a vizuális linkszöveg változatlanul csak annyi, hogy Tovább olvasom.

Tipikus hiba, ha nem figyelünk a névkalkulációra

A következő példa egy olyan akadálymentességi hibát mutat be, amivel sajnos sok weboldalon találkozom, és ebben is a névkalkuláció játssza a főszerepet.

Vegyünk egy olyan linket, amibe egy ikon fonttal megvalósított ikont teszünk:

<a href="reszletek.html" title="Részletek"><span class="ikon"></span></a>

Egy korábbi cikkemben már írtam az ikon fontok használatának akadálymentességi anomáliáiról, amiben érintettem a névadás problémáját is.

A fenti kódnál is az a kérdés, hogy vajon mi lesz a link neve.

Sokan talán azt tippelik, hogy mivel a linkünknek nincsen szöveges tartalma, de van title attribútuma, ezért a névkalkulációs algoritmus alapján az ebben definiált Részletek szöveg lesz a kikalkulált név. Ez azonban rossz tipp, mert ez a link csak látszólag üres. És ebből adódik az akadálymentességi hiba is.

Az ikon font technikára jellemző, hogy az ikont CSS-ből, a content tulajdonság segítségével illesztjük be egy HTML jelölőelem elé vagy mögé. Anno arról is írtam már egy cikket, hogy vajon valódi tartalomnak tekinthető-e a CSS-ből beillesztett content. Az biztos, hogy a névkalkulációs algoritmus alapján a ::before és az ::after pszeudoelemek beillesztett tartalma is része lesz az adott komponens szöveges tartalmának.

Példánkban tehát a link szöveges tartalma az az egy darab Unicode karakter lesz, ami az ikon fontot reprezentálja. Vagyis a link kikalkulált neve is ez az egy darab Unicode karakter lesz! Ne feledjük, hogy a szöveges tartalom erősebb névjelölt, mint a title, tehát a névkalkulációnál a title kiesik.

Már csak az a kérdés, hogy az ikont reprezentáló Unicode karakter vajon értelmes (tehát képernyőolvasóval is felolvasható), vagy sem. Ha felolvashatatlan a Unicode karakter, akkor a link neve is felolvashatatlan (értelmetlen) lesz. A példánkban szereplő linket mondjuk a VoiceOver képernyőolvasó program csak így fogja felolvasni:

Link,

Vagyis tényleg úgy hallatszik, mintha üres lenne, ami egyértelműen akadálymentességi hiba.

Persze abból is galiba lehet, ha esetleg olyan Unicode karakter reprezentálja az ikont, ami felolvasható, hiszen ilyenkor elképzelhető, hogy az ikon vizuális megjelenése, és a felolvasott név köszönőviszonyban sincs.

Megtévesztő lehet, ha valaki mondjuk az NVDA képernyőolvasóval teszteli le a példában szereplő megoldást. Gyári alapbeállítások mellett az NVDA képernyőolvasó ugyanis így fogja felolvasni a linket:

Hivatkozás, Részletek

Most akkor mégis jó a példánk? Hirtelen hogyan lett Részletek a link neve?

Elárulom, a link neve továbbra is hibás, vagyis üres (értelmetlen). Az elhangzó Részletek szöveg ugyanis nem a link neve, hanem a link kiegészítő leírása (bővebb magyarázata), ami történetesen a title attribútumból jön.

Eddig még nem említettem, de a leírás meghatározására is létezik egy kalkulációs algoritmus, amit szintén a hivatkozott W3C specifikációk írnak le. Ugyanúgy beszélhetünk „leírásjelöltekről”, ezek erősorrendjéről, és a győztes (azaz a kikalkulált) leírásról. De a leíráskalkulációra most nem térnék ki részletesen.

A kiegészítő leírást egyébként a VoiceOver képernyőolvasó is felolvassa, de a gyári alapbeállítások mellett csak a név elhangzása után néhány másodperccel. Vagyis közel sem biztos, hogy a képernyőolvasós felhasználóhoz eljut ez az információ. Amúgy a képernyőolvasó programok többségénél saját maga tudja beállítani a felhasználó, hogy a kiegészítő leírás elhangozzon-e vagy sem, és ha igen, akkor hogyan.

A példánk tehát jól mutatja, hogy nem szabad túlmisztifikálni a title attribútum akadálymentességi szerepét. A title az egyik leggyengébb, és „legingoványosabb” attribútum, amire akadálymentességi szempontból nem nagyon szabad építeni. Valószínűleg a példakódnál is csak azért használták a fejlesztők, hogy tooltip-ként megjelenhessen, de ezzel kapcsolatban is bőven akadnak anomáliák.

Példa korrekciójára több megoldás is létezik. Felmerülhet, hogy a title helyett az aria-label attribútumot használjuk, ami biztosan nevet fog adni a linknek:

<a href="reszletek.html" aria-label="Részletek"><span class="ikon"></span></a>

A képernyőolvasó szempontjából ez már akadálymentesebb megoldás, de egyéb szempontok alapján nem igazán. Az ikon fontokról szóló cikkemben is kitérek arra az alapelvre, hogy a CSS-nek nem szabad érdemi információkat közvetítenie. Ha ugyanis a CSS formázás bármilyen ok miatt nem úgy jelenik meg, ahogy tervezzük, akkor információvesztés állhat fenn. Márpedig az ikon fontok ebből a szempontból nagyon sérülékenyek, és ekkor – aria-label ide vagy oda – a látó felhasználók csak egy üres linket kapnak. Az említett cikkemben ezt is tovább boncolgatom, és alternatív megoldásokat is felvázolok.

Zárszó

Végezetül két fontos dolgot emelnék még ki a névkalkuláció kapcsán.

Adhat-e nevet a placeholder?

A névkalkulációs algoritmusban, és így a névjelöltek között sem szerepel az űrlapmezőknél használható placeholder attribútum, ugyanis a placeholder nem definiálja az űrlapmező nevét (címkéjét).

Mégis sokan ilyen megfontolásból használják a helykitöltőt, ami egyértelmű hiba. Erről bővebben a Használható-e a HTML5 placeholder attribútuma űrlapcímkeként? című cikkemben írok.

Például az alábbi űrlapmezőnek sincsen neve:

<input type="text" placeholder="Vezetéknév">

Ugyanakkor megjegyezném, hogy sajnos a névkalkulációs specifikációktól eltérően mégis sok böngészőprogram beleveszi a névkalkulációba a placeholder értékét is, ami bugnak tekinthető. Semmiképpen ne építsünk erre a viselkedésre.

Címke a névben

A 2018 júniusában megjelent új WCAG 2.1 akadálymentességi szabvány 2.5.3 alapkövetelménye azt írja elő, hogy a komponens nevében mindenképpen szerepeljen a komponens vizuálisan is látható címkéje. Mégpedig lehetőleg a név legelején.

Ez a követelmény azon látó felhasználók érdekében született, akik hangvezérléssel böngésznek.

A cikk elején említettem, hogy nekik egy interaktív komponenst a nevével kell megszólítaniuk, de ezt a nevet elvileg nem tudják (látják), hiszen a kikalkulált név csak az akadálymentességi fában van letárolva. Értelemszerűen csak a komponens vizuálisan is látható címkéjét tudják bemondani az azonosításhoz. Ezért fontos, hogy a vizuálisan látható címke szövege pontosan ugyanolyan alakban (toldalékokkal) legyen benne a kikalkulált név elején.

Persze ettől a kikalkulált név „hátrafele” még nyugodtan lehet bővebb szövegű, ahogyan a Tovább olvasom példánknál is belefűztük a hír címét. Ezt a szituációt már elvileg le tudják kezelni a hangvezérlő szoftverek, mint ahogyan azt is, ha több ugyanolyan címkéjű komponensből kell választania a felhasználónak.