Ръководство за разработчици за ARIA етикети, които наистина помагат
ARIA етикетите не са магически слой за достъпност. Използвани добре, те правят контролите разбираеми. Използвани небрежно, те скриват полезен текст и създават объркващи интерфейси.
Съдържание
- ARIA етикетите са за имена, не за извинения
- Достъпното име, казано просто
- Първо правило: предпочитайте нативен HTML и видими етикети
- Кога `aria-label` е правилният инструмент
- Кога `aria-label` е грешният инструмент
- Използвайте `aria-labelledby`, когато видимият текст вече съществува
- Използвайте `aria-describedby` за помощен текст, не за името
- Повтарящите се контроли се нуждаят от уникални имена
- Не етикетирайте всичко
- Проверявайте изчисленото име, не само кода
- Практически списък за проверка
- Тихата дисциплина на добрата ARIA
ARIA етикетите са за имена, не за извинения
ARIA е полезна, но често се използва като кръпка за неясен HTML. Именно там екипите започват да имат проблеми.
Най-честият пример е aria-label. Изглежда безобидно: добавяте низ, удовлетворявате linter, продължавате нататък. Но достъпното име не е украса. Това е името, което много помощни технологии показват на потребителите, когато навигират по бутони, връзки, полета във формуляри, заглавия, landmarks и контроли.
Ако това име е неясно, дублирано, остаряло или различно от видимия етикет, интерфейсът става по-труден за използване. Понякога е и по-лошо: aria-label може да презапише по-добър текст, който вече е присъствал в DOM.
Целта не е да добавяме повече ARIA. Целта е да направим името, ролята, състоянието и предназначението на всеки елемент от интерфейса ясни.
Достъпното име, казано просто
Повечето интерактивни елементи имат достъпно име. Екранните четци използват това име, за да обявят какво представлява елементът.
Например:
<button>Save changes</button>
Екранен четец може да обяви нещо като: „Save changes, button.“ Ролята идва от нативния елемент button. Името идва от текста вътре в него.
Това е идеалният случай: видимият текст и достъпното име съвпадат.
ARIA атрибутите за етикетиране стават полезни, когато видимият интерфейс не предоставя пълно име или когато името трябва да дойде от друг елемент. Основните атрибути са:
aria-label: предоставя низ директно върху елемента.aria-labelledby: сочи към един или повече елементи, чийто текст става име.aria-describedby: сочи към поддържащ описателен текст, а не към основното име.
Тези три са свързани, но не са взаимозаменяеми.
Първо правило: предпочитайте нативен HTML и видими етикети
Ако можете да поставите видим текст върху контролата, направете първо това.
Това е по-добре:
<button>Delete invoice</button>
От това:
<button aria-label="Delete invoice">
<svg aria-hidden="true" focusable="false">...</svg>
</button>
Вторият модел е валиден за бутон само с икона. Но ако дизайнът може да понесе видим текст, видимият текст помага на всички: потребители на екранни четци, потребители на гласово разпознаване, хора с когнитивно натоварване, хора, които сканират бързо, и хора, които използват инструменти за превод.
Това е повтаряща се тема в работата по достъпност. Нативният HTML и видимите affordances решават повече проблеми от скритите метаданни. Същият принцип важи и за семантиката на бутоните в по-широк план; ако екипът ви прави одит на UI контроли, нашият списък за проверка за достъпни уеб бутони е добро допълнение към това ръководство.
Кога aria-label е правилният инструмент
Използвайте aria-label, когато елемент има нужда от достъпно име и няма подходящ видим текст, към който да се направи препратка.
Класическият случай е бутон само с икона:
<button aria-label="Search">
<svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
<!-- icon -->
</svg>
</button>
Това е разумно. Видимата икона подсказва търсене, но самият SVG път не предоставя надеждно име. aria-label осигурява такова.
Други добри случаи включват:
- Бутон за затваряне, представен само с „X“.
- Навигационен landmark, който се нуждае от по-конкретно име, като
aria-label="Product". - Повтаряща се контрола, при която видимият контекст не е част от текста на бутона.
Например:
<nav aria-label="Primary">
...
</nav>
<nav aria-label="Footer">
...
</nav>
И двете са навигационни landmarks, но етикетите им помагат на потребителите да ги различават, когато се придвижват по landmarks.
Кога aria-label е грешният инструмент
Не добавяйте aria-label само защото тест казва, че даден елемент се нуждае от етикет. Първо поправете markup.
Лошо:
<div role="button" tabindex="0" aria-label="Submit">Submit</div>
По-добре:
<button>Submit</button>
Първият пример създава ненужна работа. Сега трябва да пресъздадете поведението от клавиатурата, disabled състоянията, поведението във формуляри и очакванията, които нативните бутони вече предоставят.
Също така избягвайте да използвате aria-label, за да преименувате видим текст по начин, който променя смисъла.
<button aria-label="Delete invoice">Remove</button>
Това изглежда дребно, но може да обърка потребители, които разчитат на гласово въвеждане. Ако видим бутон казва „Remove“, но достъпното му име е „Delete invoice“, потребител, който се опитва да каже „click Remove“, може да не получи очаквания резултат. Изискването на WCAG за „label in name“ съществува точно по тази причина: видимият текст обикновено трябва да се съдържа в достъпното име.
По-добра версия:
<button aria-label="Remove invoice">Remove</button>
Често още по-добре:
<button>Remove invoice</button>
Използвайте aria-labelledby, когато видимият текст вече съществува
Ако текстът на етикета вече е на страницата, aria-labelledby обикновено е по-добър от aria-label.
Пример:
<h2 id="billing-title">Billing address</h2>
<section aria-labelledby="billing-title">
...
</section>
Достъпното име на секцията вече идва от видимото заглавие. Избягвате дублирането на низове, което намалява грешките при превод и остарелите етикети.
Това е особено полезно за групи във формуляри:
<fieldset aria-labelledby="shipping-speed-title">
<legend id="shipping-speed-title">Shipping speed</legend>
<label>
<input type="radio" name="shipping" value="standard">
Standard
</label>
<label>
<input type="radio" name="shipping" value="express">
Express
</label>
</fieldset>
В много случаи нативният legend е достатъчен без ARIA. Важното е, че видимите етикети трябва да водят. ARIA трябва да свързва съществуващ смисъл, а не да създава втора, частна версия на него.
Използвайте aria-describedby за помощен текст, не за името
Описание не е етикет.
Разгледайте това поле:
<label for="password">Password</label>
<input id="password" type="password" aria-describedby="password-help">
<p id="password-help">Use at least 12 characters.</p>
Достъпното име е „Password.“ Описанието е „Use at least 12 characters.“ Екранен четец може да обяви и двете, но те служат на различни цели.
Не правете това:
<input type="password" aria-label="Use at least 12 characters">
Това именува полето според инструкцията, а не според понятието. Потребител, който навигира във формуляр, първо иска да знае какво представлява полето, а след това какви ограничения се прилагат.
Това разграничение е важно и при състояния на грешка:
<label for="email">Email</label>
<input
id="email"
type="email"
aria-invalid="true"
aria-describedby="email-error"
>
<p id="email-error">Enter an email address in the format [email protected].</p>
Етикетът остава стабилен. Съобщението за грешка става поддържащ контекст.
Повтарящите се контроли се нуждаят от уникални имена
Списъците и картите са местата, където ARIA етикетите често стават необходими.
Лошо:
<button>Delete</button>
<button>Delete</button>
<button>Delete</button>
Потребител на екранен четец, който навигира по бутони, може да чуе „Delete, button“ три пъти без контекст.
Добре:
<button aria-label="Delete report: Q4 revenue">Delete</button>
<button aria-label="Delete report: Hiring plan">Delete</button>
<button aria-label="Delete report: Vendor list">Delete</button>
Това е легитимна употреба на aria-label: видимият текст остава кратък, докато достъпното име включва обекта.
Но използвайте този модел внимателно. Ако името на обекта е видимо наблизо, aria-labelledby може да е по-лесен за поддръжка:
<article>
<h3 id="report-q4">Q4 revenue</h3>
<button aria-labelledby="delete-q4 report-q4" id="delete-q4">Delete</button>
</article>
Достъпното име става „Delete Q4 revenue.“ Това избягва дублирането на заглавието на отчета в атрибут.
Не етикетирайте всичко
Не всеки елемент се нуждае от ARIA етикет.
Статичният текст обикновено не се нуждае. Декоративните икони също не. Контейнерите не се нуждаят, освен ако нямат смислена landmark или widget роля. Прекомерното етикетиране може да направи страницата шумна и по-трудна за навигация.
За изображения използвайте модела, специфичен за изображения: значимите изображения се нуждаят от полезен alt; декоративните изображения се нуждаят от празен alt="". Не използвайте ARIA етикети като заместител на добър текст за изображения. Ако екипът ви смесва тези понятия, прегледайте отново прагматичен alt текст за изображения и отделете алтернативите за изображения от имената на контролите.
Честа грешка е да се дава aria-label на всеки SVG. Ако SVG е вътре в бутон и бутонът вече има име, иконата обикновено трябва да бъде скрита от помощните технологии:
<button aria-label="Open menu">
<svg aria-hidden="true" focusable="false">...</svg>
</button>
В противен случай потребителят може да чуе излишни или странни съобщения в зависимост от комбинацията от браузър и помощна технология.
Проверявайте изчисленото име, не само кода
Грешките в достъпността често оцеляват при code review, защото markup изглежда правдоподобен.
Съвременните инструменти за разработчици в браузърите могат да показват изчисленото дърво за достъпност. В Chrome, Edge, Firefox и Safari инспектирайте елемента и потърсете информация за достъпността, като роля, име и описание. Проверявате три неща:
- Ролята такава ли е, каквато очаквате?
- Достъпното име ясно и конкретно ли е?
- Описанието полезно ли е, без да заменя името?
След това тествайте няколко потока с истински екранен четец. Не е нужно да ставате експерт по помощни технологии на пълен работен ден, за да уловите основното. В macOS VoiceOver е вграден. В Windows NVDA е широко използван и безплатен. На мобилни устройства тествайте с VoiceOver на iOS и TalkBack на Android, когато е релевантно.
Автоматизираните инструменти са полезни, но не могат надеждно да преценят дали „Open“, „Read more“ или „Delete“ имат достатъчен контекст. Приемайте автоматизацията като мрежа, а не като съдия. Това прилича на одит на производителността: отчетът може да ви насочи към подозрителни области, но все пак трябва да интерпретирате въздействието. Същият спокоен подход, който препоръчваме за четене на Lighthouse отчет без паника, важи и тук.
Практически списък за проверка
Преди да пуснете ARIA етикети, попитайте:
- Може ли това вместо това да бъде нативен HTML?
- Има ли видим текст, който трябва да се използва като етикет?
- Ако съществува видим текст, достъпното име включва ли го?
- Уникални ли са повтарящите се контроли, когато се навигират извън визуален контекст?
- Помощният текст свързан ли е с
aria-describedby, вместо да бъде насилствено вкаран в етикета? - Декоративните икони скрити ли са от помощните технологии?
- Проверил ли е някой изчисленото достъпно име в browser dev tools?
- Направен ли е поне един преглед с реален екранен четец за критичния поток?
Този списък улавя повечето проблеми с етикетите, преди да се превърнат в проблеми за потребителите.
Тихата дисциплина на добрата ARIA
Добрата работа с ARIA рядко е драматична. Тя е предимно сдържаност.
Използвайте истински бутони. Използвайте истински етикети. Поддържайте видимите и достъпните имена подравнени. Добавяйте aria-label само когато няма по-добър видим източник. Използвайте aria-labelledby, когато страницата вече съдържа правилния текст. Използвайте aria-describedby за поддържащи инструкции и грешки.
Уеб платформата дава на разработчиците много неща безплатно, когато я използваме директно. ARIA е там за пропуските. Умението е да знаете кога наистина има пропуск.