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
<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,taband more. Newer React Native versions also accept the web-styleroleprop.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) andaccessibilityElementsHidden(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
Textscales by default; test at the largest sizes and let layouts wrap instead of clipping. UsemaxFontSizeMultipliersparingly 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:
- 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.
- Fix: make the card
accessiblewith a label "Pasta bake, rated 4.5 out of 5", give the heart its own label andselectedstate (so it stays a separate control), and hide the decorative stars. - 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.