Accessibility Label — what it is, basics and how to use for iOS and Android

Author: IT Sectr Published: 2026-05-16 Reading time: 9 min

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 — the name of an element announced by the screen reader; set via accessibilityLabel in iOS and contentDescription in Android
  • Label should match the visible text of the element or replace it for non-text components
  • Each Label must be unique within the screen — duplicate labels disorient the user
  • Localization of Labels is required: labels are translated into all supported languages of the application
  • For custom controls, Label is set programmatically via override of the property or NSObject protocol

What is Accessibility Label

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.

Label and WCAG 4.1.2: Name, Role, Value

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.

iOS: accessibilityLabel property

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:

swift
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:

swift
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.

NSAttributedString and accessibilityLabel

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.

Android: Label via contentDescription

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:

kotlin
binding.iconStar.contentDescription = "Product in favorites"

// For custom View with multiple elements
binding.customCard.setContentDescription(
    "\(title) for \(price)")

In XML for decorative elements:

xml
<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.

Compose: semantics and contentDescription

In Jetpack Compose, the Label is set via the semantics modifier:

kotlin
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.

Label and Hint: role distinction

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:

  • Label: “Delete”
  • Hint: “Permanently deletes the selected photo”
  • VoiceOver: “Delete. Permanently deletes the selected photo”

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.

When Hint is not needed

  • Element with intuitively understandable action (“Back”, “Close” — Label is sufficient)
  • Label already describes the result (“Send message” — verb in the name itself)
  • System controls (UISwitch, UIButton with system type) — their behavior is standard

Common mistakes: Label instead of Hint

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”.

Localization and best practices

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:

  • Start with the key word — “Search products”, not “Field for searching products”
  • Do not include the words “button”, “field”, “image” — the role is added automatically
  • Use natural language understandable to the target audience
  • Avoid abbreviations (except commonly accepted ones: “pcs.”, “kg”) — screen reader reads them literally
  • For input elements, add an example: “Email (example@domain.com)”

Brand consistency of Labels

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.

Labels for form elements

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”.

How to test accessibility labels

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:

swift
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:

kotlin
@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.

VoiceOver rotor and quick navigation

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.

CI/CD pipeline integration

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

How does Accessibility Label differ from Accessibility Hint?

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.

Do I need to set Label for UILabel with text?

In iOS, UILabel automatically gets an accessibilityLabel equal to its text. No additional setup is needed. In Android, TextView behaves similarly.

How to set Label for a custom UIView?

Set isAccessibilityElement = true on the parent View and override accessibilityLabel, returning concatenated text from child elements. For complex components, use concatenation with a separator.

How to avoid duplicate Labels on the screen?

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.

Can Label be used to hide an element from screen reader?

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

  • Accessibility Label — the name of an element for VoiceOver and TalkBack; set via accessibilityLabel in iOS and contentDescription in Android
  • Label should match the visible text of text elements; for non-text elements (icons, images) it is set manually
  • Hint answers “What will happen?” and does not duplicate the Label — these properties have different roles
  • Each Label must be unique on the screen; duplication disorients the screen reader user
  • Localization of labels is mandatory via NSLocalizedString (iOS) and @string (Android)
  • Test Labels automatically via UI tests (XCUIApplication, AccessibilityCheckRule) and manually via VoiceOver
  • Hide decorative elements via isAccessibilityElement = false or importantForAccessibility = “no”

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.

Discuss the project

Read also