Accessibility Label is the name of an interface element that VoiceOver (iOS) or TalkBack (Android) announces when focused. In iOS, the property is called accessibilityLabel, in Android — contentDescription for elements that don’t contain text. According to Apple Developer Documentation, 2024, the label is the foundation of accessibility: without it, the user cannot identify the element. The label must be unique within the screen and reflect the essence of the element in clear language.
Key Takeaways
Accessibility Label is a string property that defines the name of an element for assistive technologies. When the user swipes across the screen with VoiceOver enabled, the screen reader reads the Label of the focused element. Without a label, the user only hears the element type: “button”, “image” — without indicating its purpose.
According to Google I/O 2024, “Accessibility Testing”, 35% of critical accessibility violations in store applications are related to missing or incorrect Labels. Accessibility Scanner on Android detects a missing label as a highest severity error.
A fundamental limitation: Label must not contain the element type. VoiceOver and TalkBack automatically add the role (button, header, link) to the announcement. If the Label contains “Send button”, the user will hear: “Send button, button” — duplication.
WCAG 4.1.2 (Level A) requires every user interface element to have a programmatically determinable name, role, and value. Accessibility Label provides the name. If the Label is missing, the criterion is considered violated, and the application does not pass basic certification.
In iOS, accessibilityLabel is inherited by all UIView from the UIAccessibility protocol. If an element contains text (UIButton with title, UILabel with text), the Label is automatically set to that text. For UIImageView, custom controls, and containers, the Label needs to be set manually.
Example for a custom table cell:
class CustomTableViewCell: UITableViewCell {
let titleLabel = UILabel()
let priceLabel = UILabel()
override func awakeFromNib() {
super.awakeFromNib()
self.isAccessibilityElement = true
self.accessibilityLabel =
"\(titleLabel.text ?? "") - \(priceLabel.text ?? "")"
}
}
For custom UIView, you can override the accessibilityLabel getter:
class RatingView: UIView {
var rating: Int = 5
override var accessibilityLabel: String? {
get { return "Rating: \(rating) out of 5" }
set {}
}
}
Apple HIG, 2024 advises: if an element consists of several sub-elements (e.g., a product card with name and price), combine them into one accessibility element with a composite Label. Set isAccessibilityElement = true on the parent and false on children.
If UILabel uses NSAttributedString, accessibilityLabel defaults to .string (plain text). If you need to pass a semantically different value (e.g., a symbol icon reads as “Star” instead of the ★ character), explicitly set accessibilityLabel. VoiceOver does not read Unicode characters meaningfully.
In Android, contentDescription serves as the Label for ImageView, ImageButton, and custom Views. For TextView and Button with built-in text, setting contentDescription is not required — TalkBack reads the text automatically.
Programmatic setting via Kotlin:
binding.iconStar.contentDescription = "Product in favorites"
// For custom View with multiple elements
binding.customCard.setContentDescription(
"\(title) for \(price)")
In XML for decorative elements:
<ImageView
android:contentDescription="@null"
android:src="@drawable/divider"
android:importantForAccessibility="no" />
The importantForAccessibility = “no” property completely excludes the element from the accessibility tree. In iOS, the equivalent is isAccessibilityElement = false.
In Jetpack Compose, the Label is set via the semantics modifier:
Image(
painter = painterResource(R.drawable.ic_search),
contentDescription = "Search products",
modifier = Modifier.semantics {
contentDescription = "Search products"
}
)
In Compose, contentDescription is a required parameter for Image — without it, the code won’t compile (warning). This forcibly improves accessibility through API design.
Accessibility Label answers the question “What is this element?”. Hint (accessibilityHint in iOS, additional text in contentDescription in Android) — “What will happen upon interaction?”. VoiceOver announces them sequentially: first Label, then Hint.
Example for a delete button:
According to Deque University, 2024, proper separation of Label and Hint improves task completion rate for VoiceOver users by 28%. Users with cognitive impairments are particularly dependent on Hint: when unsure about pressing “Delete” without explanation, 40% refuse the action.
A frequent mistake: writing “Delete button” in Label instead of “Delete”. The element type (Button) is added by VoiceOver automatically through a trait. As a result, the user hears: “Delete button, button” — duplication. Correct Label: “Delete”, Hint: “Deletes the selected photo”.
Label localization is mandatory — it goes through standard mechanisms: NSLocalizedString in iOS, string resources @string/ in Android. Never set a Label by concatenation in English without localization.
Good Label rules, based on W3C WCAG 2.2:
Use a single glossary for Labels across the application. If one screen says “Favorites” and another says “Bookmarks”, the user is disoriented. Create an accessibility terminology table — coordinate with designers and localizers.
For input fields (UITextField, EditText), the Label should match the placeholder or field label. However, the placeholder often disappears after entering text. Use accessibilityLabel for the permanent name and accessibilityValue for the current field content — this is the WCAG 4.1.2 standard. Solution: set accessibilityLabel statically (equal to the field label), and accessibilityValue dynamically (equal to the entered text). In iOS this is automatic, but for custom fields — manually by overriding accessibilityValue. Verify that VoiceOver reads: “Email, example@domain.com, text field” instead of “, text field”.
Automated testing is the only way to guarantee Label correctness on all screens. iOS provides XCUIApplication with access to .label, Android — AccessibilityCheckRule and setContentDescription.
Example test for iOS:
func testLabelsAreUnique() {
let app = XCUIApplication()
app.launch()
let allButtons = app.buttons.allElementsBoundByIndex
let labels = allButtons.compactMap { $0.label }
let uniqueLabels = Set(labels)
XCTAssertEqual(labels.count, uniqueLabels.count,
"Duplicate Labels found")
}
Example for Android with Espresso:
@Test
fun testButtonHasAccessibilityLabel() {
onView(withId(R.id.btnSubmit))
.check(matches(
withContentDescription(containsString("Send"))
))
}
Manual testing: enable VoiceOver (iOS) or TalkBack (Android) and swipe right through all elements on the screen. Each element should receive a meaningful announcement. If you only hear “button” or “image” — the Label is missing.
After setting up the Label, VoiceOver users can use the rotor for quick navigation: modes “Buttons”, “Headings”, “Links”, and others. If the Label is set correctly, VoiceOver includes the element in the corresponding rotor mode. Verify that all buttons are visible in “Buttons” mode, all headings in “Headings”.
Label also affects VoiceOver search. The user can type a word in search mode, and VoiceOver will move focus to the element with a matching Label. Therefore, Labels should contain key words that the user will search for.
Add Label checking to the pipeline. On iOS, use XCUITest with fastlane scan. On Android, use Accessibility Test Framework with the AccessibilityCheckRule that detects empty contentDescription. This prevents regressions when merging new screens.
Frequently Asked Questions
Label identifies the element (“Search”), Hint explains the result of the action (“Opens the search screen”). VoiceOver announces the Label immediately on focus, and Hint — in detailed descriptions mode.
In iOS, UILabel automatically gets an accessibilityLabel equal to its text. No additional setup is needed. In Android, TextView behaves similarly.
Set isAccessibilityElement = true on the parent View and override accessibilityLabel, returning concatenated text from child elements. For complex components, use concatenation with a separator.
Add context to repeating elements: “Buy iPhone 15”, “Buy iPhone 15 Pro”. Automate the check via UI tests — collect all Labels and verify there are no duplicates.
No. To hide an element, use isAccessibilityElement = false in iOS or importantForAccessibility = “no” in Android. An empty Label does not hide the element — the screen reader will read “untitled”.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also