Content Description — свойство за достъпност, което предава текстово описание на нетекстово съдържание на помощните технологии. В iOS това е атрибутът accessibilityHint за UIView, в Android — contentDescription в XML маркирането. Според данните на W3C WCAG 2.2, 2023, липсата на текстови алтернативи за нетекстово съдържание е едно от най-честите нарушения на достъпността в мобилните приложения. Правилно попълнените описания правят приложението достъпно за хора с увредено зрение, които използват VoiceOver и TalkBack.
Основни точки
Content Description — низово свойство на елемент от интерфейса, което предава текстовото представяне на визуално съдържание на помощните технологии. Screen reader (VoiceOver в iOS, TalkBack в Android) чете описанието вместо да се опитва да разпознае визуално елемента. Описанието се прилага към изображения без текстов слой, икони, графики, персонализирани контроли и всякакви нетекстови елементи.
Според данните на Google Material Design, 2024, елементите без contentDescription нарушават правилото WCAG 1.1.1 (Non-text Content). Проверката на Accessibility Scanner показва, че до 40% от иконите в магазинните приложения нямат описание. Потребителят на VoiceOver чува само “изображение” или “бутон” без уточнение — такъв интерфейс става неизползваем за навигация.
Content Description не замества видимия текст на елемента. Ако бутонът съдържа текстов етикет “Изпрати”, не е необходимо допълнително описание — screen reader ще прочете текста. За изображения, икони и полета за въвеждане описанието е задължително.
Инструментите Accessibility Scanner (Android) и Xcode Accessibility Inspector (iOS) автоматично проверяват наличието на описания. Препоръчва се тези проверки да се извършват на всеки екран преди пускане.
Потребителят с увредено зрение разчита на VoiceOver, за да разбере интерфейса. Ако иконата на количката няма описание, той чува само “бутон”. За да разбере какво прави бутонът, трябва да го натисне на сляпо — риск от необратимо действие. Описанието “Премахни продукта от количката” решава този проблем за секунда.
Потребителят с временни ограничения (силно слънце навън, счупен екран) също използва VoiceOver. Според Apple Accessibility Report, 2023, около 20% от потребителите на VoiceOver нямат трайни увреждания на зрението — включват тази функция ситуационно.
Критерият WCAG 1.1.1 (ниво A) изисква всяко нетекстово съдържание да има текстова алтернатива. Изключение: съдържание, което е декоративно, използва се само за визуален дизайн или не носи информация. Тест за декоративност: ако премахнем елемента, променя ли се смисълът на страницата? Ако не — може да бъде скрит от screen reader.
Accessibility Label (accessibilityLabel в iOS) — името на елемента, което screen reader произнася при фокусиране. Content Description (accessibilityHint в iOS) — допълнително обяснение, което се озвучава след името и информира за резултата от действието.
Разликата се вижда добре на примера на бутона “Количка”. Label: “Количка”. Description: “Ще отвори екрана за поръчка”. VoiceOver казва: “Количка. Ще отвори екрана за поръчка”. Ако е зададен само Label, потребителят няма да знае какво ще се случи след натискане.
| Свойство | iOS | Android | Предназначение |
|---|---|---|---|
| Label | accessibilityLabel | contentDescription | Име на елемента (бутон, поле, изображение) |
| Description | accessibilityHint | contentDescription (разширена) | Обяснение на действието или значението |
| Trait | accessibilityTraits | role / className | Роля на елемента (бутон, заглавие) |
Правило: Label отговаря на въпроса “Какво е това?”, Description — “Какво ще се случи?”. В Android contentDescription може да изпълнява и двете роли, но на практика е по-добре да ги разделяте: използвайте конкатенация “[име], [обяснение]”.
За сложни жестове (плъзгане за изтриване, дълго натискане за контекстно меню) accessibilityHint е задължителен. Потребителят на VoiceOver не знае за скритите жестове, ако не са описани. Посочете: “Плъзнете наляво за изтриване” в hint на елемента.
На платформата iOS accessibilityHint се задава чрез едноименното свойство на UIView или NSObject. Стойност — низ до 80 знака. VoiceOver чете hint след label, ако е включен режимът на подробни описания (в настройките на VoiceOver — “Verbosity”).
Пример за задаване на hint за персонализиран бутон:
import UIKit
class CustomButton: UIButton {
override func awakeFromNib() {
super.awakeFromNib()
self.accessibilityLabel = "Добави в любими"
self.accessibilityHint = "Ще запази продукта в списъка с любими"
}
}
За UIImageView без текстово съдържание е задължително да се зададат isAccessibilityElement = true и accessibilityHint:
let imageView = UIImageView(image: UIImage(named: "chart-sales"))
imageView.isAccessibilityElement = true
imageView.accessibilityHint = "Графика на продажбите за последното тримесечие"
VoiceOver чете: “Графика на продажбите за последното тримесечие”. Ако hint е празен — само “изображение”. Apple HIG, 2024 препоръчва да не се използват глаголи като “натиснете” или “докоснете” в hint — VoiceOver автоматично добавя инструкция за жест.
В SwiftUI hint се задава чрез верижен модификатор:
Image(systemName: "trash")
.accessibilityLabel("Изтрий")
.accessibilityHint("Ще изтрие безвъзвратно избрания елемент")
SwiftUI автоматично комбинира модификатори за съставни view. Ако Image се намира вътре в Button, SwiftUI използва label на бутона като основен accessibilityLabel.
В Android contentDescription се задава или в XML маркирането, или програмно чрез setContentDescription(). TalkBack озвучава описанието при фокусиране на елемента.
Пример в XML:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_search"
android:contentDescription="Търсене на продукти" />
Програмно задаване за динамични елементи:
binding.iconSearch.contentDescription =
"Търсене. Ще отвори екрана за търсене с филтри"
За декоративни изображения (разделители, фонове, декоративни икони) задайте contentDescription = "@null" или setContentDescription(null) — TalkBack ще пропусне такъв елемент. В XML: android:contentDescription="@null". Празният низ "" не работи — TalkBack пак ще каже “изображение”.
За ImageButton винаги задавайте contentDescription — TalkBack не вижда текста върху изображението. За CheckBox описанието трябва динамично да се променя: “Избрано” / “Не е избрано” вместо статично описание. Използвайте setContentDescription в слушателя за състояние.
Информативност — описанието трябва да предава смисъла, а не външния вид. Не “Синя икона с отметка”, а “Продуктът е добавен в количката”. Screen reader не се интересува от цветове — интересува се от резултата.
Краткост — оптимална дължина 2–4 думи (до 80 знака). Дългите описания забавят навигацията: VoiceOver чете последователно, всяка дума е секунда от времето на потребителя. Според Apple WWDC 2023, “Accessibility by Design”, фраза, по-дълга от 5 секунди четене, прекъсва когнитивния поток.
Уникалност — на един екран не трябва да има два елемента с еднакво описание. Потребителят няма да може да различи какъв резултат ще доведе фокусирането върху първия и втория елемент. Ако има няколко бутона “Купи” — добавете идентификатор: “Купи iPhone 15”, “Купи iPhone 15 Pro”.
Локализация — Content Description се превежда на всички езици, които приложението поддържа. Грешката в локализацията на описанието е една от честите причини за провал на Accessibility Review в App Store.
Изследването на Nielsen Norman Group, 2024 показа, че оптималната дължина на описанието за screen reader е 3–5 думи (до 50 знака). По-дългите описания намаляват скоростта на навигация с 30%, тъй като потребителят трябва да изчака завършването на четенето преди следващата стъпка.
Излишество — описанието дублира видимия текст. Ако бутонът съдържа текст “Изпрати”, не задавайте accessibilityHint = “Бутон изпрати”. VoiceOver ще прочете текста автоматично, а hint ще добави ненужен шум.
Объркване с Label — използване на contentDescription вместо label за текстови бутони. В iOS accessibilityLabel трябва да съвпада с текста на бутона (или да бъде празен, ако текстът вече е видим), а hint само обяснява действието. Според Google Testing Blog, 2024, 23% от проверените приложения в Play Store имат дублиращи се описания.
Игнориране на динамиката — описанието не се актуализира при промяна на състоянието. Например при превключвателя “Wi-Fi” описанието остава “Включи Wi-Fi” дори след включване. Правилно: динамично да промените описанието на “Изключи Wi-Fi” чрез наблюдение на състоянието.
След актуализация на дизайна (смяна на икони, пренареждане на елементи) Content Description често се губи. Причина: дизайнерът заменя изображението, разработчикът не проверява свойствата за достъпност на новия актив. Решение: направете проверката на достъпността задължителна стъпка в code review — добавете контролен списък с точка “Content Description актуализиран ли е?”.
func testContentDescriptionExists() {
let app = XCUIApplication()
app.launch()
let image = app.images["chart-sales"]
XCTAssertNotNil(image.label)
XCTAssertGreaterThan(image.label.count, 0)
}
Често задавани въпроси
Потребителят на VoiceOver или TalkBack ще чуе само “изображение” или “бутон” — без посочване на предназначението. Това нарушава WCAG 1.1.1 и прави приложението недостъпно за хора с увредено зрение.
Не. Ако бутонът съдържа текстов етикет, VoiceOver ще го прочете автоматично. Описанието (accessibilityHint) може да се добави за обяснение на резултата от натискането, но Label не е необходим.
В iOS задайте isAccessibilityElement = false. В Android задайте contentDescription = "@null". Screen reader напълно ще пропусне такъв елемент, без да издава звук.
В iOS използвайте NSLocalizedString за accessibilityHint, в Android — низови ресурси чрез @string/. Преводът на описания е задължителен за всички поддържани езици.
Добавете UI тестове, които проверяват наличието на описание за всички ImageView. В iOS — XCUIApplication, в Android — AccessibilityCheckRule от Espresso. Accessibility Scanner може да се пусне в CI чрез команден ред.
Заключение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също