Content Description — свойство доступности, которое передаёт текстовое описание непереходного контента вспомогательным технологиям. В iOS это атрибут accessibilityHint для UIView, в Android — contentDescription в XML-разметке. По данным W3C WCAG 2.2, 2023, отсутствие текстовых альтернатив для нетекстового контента — одно из самых частых нарушений accessibility в мобильных приложениях. Правильно заполненные описания делают приложение доступным для людей с нарушениями зрения, пользующихся 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) — это имя элемента, которое screenreader произносит при фокусе. 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 задаётся через chain-модификатор:
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 часто теряется. Причина: дизайнер заменяет изображение, разработчик не проверяет accessibility-свойства нового ассета. Решение: сделать проверку accessibility обязательным шагом 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 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также