Skip to main content
Back to module
Mobile App Production · Quality

Mobile accessibility

Reading50mLesson 3 of 3 in this module

What you'll learn

  • Test with VoiceOver and TalkBack
  • Give custom controls a label, role and state
  • Group related content and hide decorative elements
  • Support large text, sufficient contrast, big touch targets and reduced motion

Make screens work with VoiceOver and TalkBack, large text and reduced motion.

Why it matters

Around one in six people worldwide live with a significant disability (WHO estimate), and many more use accessibility features temporarily or by preference: larger text, a screen reader in the car, reduced motion. Accessible apps reach more users, meet legal requirements in many countries and score better in store review. Phones have excellent built-in assistive technology; your job is to give it the information it needs.

Screen readers on phones

  • VoiceOver (iOS): Settings > Accessibility > VoiceOver. Swipe right/left to move between elements, double-tap to activate, three-finger swipe to scroll. Set the Accessibility Shortcut (triple-click the side button) so you can toggle it quickly.
  • TalkBack (Android): Settings > Accessibility > TalkBack. Swipe right/left to move, double-tap to activate. Many phones offer a volume-key shortcut.

Before you turn either on for the first time, practise the gestures and learn how to turn it off again, because normal taps stop working while it is on.

The screen reader reads each element's label, role ("button", "heading") and state ("selected", "disabled").

The key React Native props

JavaScript
<Pressable
  onPress={toggleFavourite}
  accessibilityRole="button"
  accessibilityLabel="Favourite"
  accessibilityHint="Adds this recipe to your favourites"
  accessibilityState={{ selected: isFavourite }}
  hitSlop={10}
>
  <HeartIcon filled={isFavourite} />
</Pressable>
  • accessibilityLabel: what the element is. Essential for icon-only buttons; without it the reader says "button" and nothing else.
  • accessibilityRole: button, link, header, image, switch, checkbox, tab and more. Newer React Native versions also accept the web-style role prop.
  • accessibilityState: selected, checked, disabled, busy, expanded.
  • accessibilityHint: an optional short description of the result, when the label is not enough.
  • accessible={true} on a container groups its children into one element, so a card is read as one item ("Pasta bake, 30 minutes, 4 stars") instead of five separate swipes.
  • importantForAccessibility="no-hide-descendants" (Android) and accessibilityElementsHidden (iOS) hide purely decorative elements.

Text and native controls such as Switch and TextInput already expose sensible information; custom controls built from Pressable and View need these props.

Beyond screen readers

  • Text size: users can enlarge text (Dynamic Type on iOS, font size on Android). React Native Text scales by default; test at the largest sizes and let layouts wrap instead of clipping. Use maxFontSizeMultiplier sparingly where a layout truly cannot grow.
  • Colour contrast: at least 4.5:1 for normal text (WCAG AA). Do not use colour alone to show state; add an icon or text.
  • Touch targets: at least 44 pt (iOS) or 48 dp (Android), as in Mobile Development Basics.
  • Reduced motion: AccessibilityInfo.isReduceMotionEnabled() lets you swap large animations for fades.
  • Focus and announcements: after an important change (an error appears), move focus or call AccessibilityInfo.announceForAccessibility("Payment failed").

Worked example: auditing a recipe card

A card shows a photo, a title, a heart icon and a "4.5" rating with star icons. With VoiceOver on:

  1. Swiping lands on the image ("image"), the title, the heart ("button") and each of five stars separately. That is eight swipes per card, and the heart has no name.
  2. Fix: make the card accessible with a label "Pasta bake, rated 4.5 out of 5", give the heart its own label and selected state (so it stays a separate control), and hide the decorative stars.
  3. Now each card is two swipes: the card (double-tap opens it) and "Favourite, button, selected".

Automated checks help too: React Native Testing Library's getByRole queries fail when roles or labels are missing, and Android's free Accessibility Scanner app flags small targets and low contrast. But only testing with a real screen reader shows whether the experience makes sense.

Common mistakes

  • Icon buttons with no label.
  • Every decorative element announced separately.
  • Disabling font scaling instead of fixing layouts.
  • Colour as the only signal for errors or selection.
  • Never trying the app with VoiceOver or TalkBack.

Quick recap

  • VoiceOver and TalkBack read label, role and state; give custom controls all three.
  • Group related content with accessible, hide decoration, announce important changes.
  • Support large text, sufficient contrast, big touch targets and reduced motion.
  • Test with a real screen reader on a real phone.

Try it

In the Do tab you will audit one screen of your app with VoiceOver or TalkBack, fix what you find and test again.

Key terms (6)

VoiceOver
The iOS screen reader; swipe to move between elements and double-tap to activate.
TalkBack
The Android screen reader, used with similar swipe and double-tap gestures.
accessibilityLabel
A React Native prop that says what an element is; essential for icon-only buttons.
accessibilityRole
A prop that tells assistive technology what kind of element this is, such as button, header or switch.
accessibilityState
A prop that reports an element's state, such as selected, checked, disabled or expanded.
Dynamic Type
The iOS setting that lets users enlarge text; layouts should wrap rather than clip at large sizes.

Recap

  • VoiceOver and TalkBack read each element's label, role and state; custom controls need all three.
  • Group a card's content with accessible and hide decorative elements.
  • Announce important changes or move focus to them.
  • Support large text, 4.5:1 contrast, 44 pt / 48 dp targets and reduced motion.
  • Automated checks help, but test with a real screen reader on a real phone.
Also in this lesson: