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:
aria-labelledby
attribútumaria-label
attribútum- 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.) - az adott komponens szöveges tartalma (ha a komponensnek lehet ilyenje)
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ó.
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
című hírt">Tovább olvasom
Átadásra került Budapest 15. mentőállomása a Szent Márton Gyermekmentő Szolgálat jóvoltából
</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 következő bekezdéseket utólag töröltem.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 Törölt bekezdések végeplaceholder
értékét is, ami bugnak tekinthető. Semmiképpen ne építsünk erre a viselkedésre.
Frissítés (2019.augusztus): A készülő HTML Accessibility API Mappings 1.0 specifikáció névkalkulációs algoritmusába mégis visszakerült, hogy az űrlapmezők esetén a placeholder
is névjelölt (a leggyengébb súllyal).
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.