skip to content

In React Native, what does accessible={true} on a View do to the elements inside it for VoiceOver and TalkBack?

level: juniorimportance: should knowfreq 42%

answer

  1. one focus stop, not five
  2. children stop being separate elements
  3. iOS composes a label from child text
  4. touchables are accessible by default
  5. grouped buttons become unreachable

basics

~20 s

It turns the View into a single accessibility element, so the screen reader focuses the group once and reads its children together instead of stopping on each child; Pressable and the other touchables are already accessible by default.

solid answer

~50 s

`accessible={true}` makes a `View` one accessibility element: VoiceOver and TalkBack land on the whole group in one swipe, and its children are no longer separate focus stops. On iOS it maps to the native accessibility-element flag, and when the group has no `accessibilityLabel`, React Native builds one from its children's text; on Android it maps to native `focusable`, and TalkBack reads the group's content together. `Pressable` and the other touchables are accessible by default, a plain `View` is not. In an email list I group each row, so sender, subject and time are one stop instead of four. The trap is grouping something that contains its own controls: a Star button inside a grouped row can no longer be reached on its own, so it must move out of the group or become a custom action.

code

tsx · 22 lines
tsx
import {Pressable, Text, View} from 'react-native';

type Email = {id: string; sender: string; subject: string; time: string};

export function MailboxHeader({unread}: {unread: number}) {
  return (
    <View accessible>
      <Text>Inbox</Text>
      <Text>{unread} unread</Text>
    </View>
  );
}

export function EmailRow({email, onOpen}: {email: Email; onOpen: (id: string) => void}) {
  return (
    <Pressable onPress={() => onOpen(email.id)}>
      <Text>{email.sender}</Text>
      <Text>{email.subject}</Text>
      <Text>{email.time}</Text>
    </Pressable>
  );
}

go deeper

for a junior

Recall that accessible={true} turns a View into one focus stop, and that Pressable and the touchables are accessible without setting it.

for a middle

Explain how grouping maps to each platform, how iOS composes a label from children, and why a nested button inside a group becomes unreachable.

for a senior

Show how you decide what to group on a dense screen, when to write an explicit label, and how you confirm the swipe count with VoiceOver and TalkBack.

for a principal

Discuss setting grouping conventions in shared list and card components so every feature team ships rows that read as one element with the same shape.

## What the prop does In React Native, `accessible` is a prop on `View` (and on everything built on it) that marks the view as an **accessibility element**: one thing a screen reader can land on. **VoiceOver** (iOS) and **TalkBack** (Android) move through a screen one element at a time, usually with a one-finger swipe. By default a plain `View` is not an element; it is a container, and the reader visits the elements inside it one by one. When you set `accessible={true}` on a `View`: - The view becomes **one focus stop**. A single swipe lands on the whole group. - Its descendants **stop being separate stops**. The reader treats them as content of the group rather than things to visit. - On **iOS**, `accessible` becomes the native accessibility-element flag. If the group has no `accessibilityLabel`, React Native builds a label by joining the text of its children, so the group still says something. - On **Android**, `accessible` becomes native `focusable`, and TalkBack speaks the content of the focused group. The React Native docs add a caution worth quoting in an interview: `accessible` makes a view **discoverable**, but it does not guarantee that VoiceOver or TalkBack will focus that exact view, because VoiceOver does not allow nested accessibility elements and TalkBack may choose to focus a parent instead. ## What is accessible by default | Component | Accessible by default? | |---|---| | `Pressable` | yes (unless `accessible={false}`) | | `TouchableOpacity` and the other touchables | yes | | `Text` | on iOS, yes; on Android, only with `onPress` or `onLongPress` (TalkBack still reads plain text) | | `View` | no, it is a container until you set `accessible` | That default is why a tappable email row built with `Pressable` already behaves as one stop: the `Text` children inside it are read as the row's content. ## Why grouping helps Without grouping, an email row with a sender, a subject, a snippet and a time costs four swipes, and the user has to remember which subject belonged to which sender. With the row grouped: 1. One swipe per email. 2. The whole row is read in one utterance: sender, subject, snippet, time. 3. Double-tapping activates the row as a unit, which matches what a sighted user does. Grouping is also the right tool for non-interactive clusters that only make sense together, such as a mailbox header reading "Inbox, 3 unread", where the count alone would be meaningless. ## When grouping hurts - **Controls inside the group disappear.** A Star or Archive button nested inside a grouped row is no longer a separate element, so a screen-reader user cannot reach it. Move the control out of the group, or expose its operation as a custom action on the row with `accessibilityActions`. - **Long groups become walls of speech.** Grouping a whole card with ten fields forces the user to listen to everything to find one value. - **The composed label can be clumsy.** The label React Native builds on iOS follows the children's order and includes every text, decorative ones too. When the row needs a specific phrasing such as "Unread. From Ana. Invoice for March. 9:41", write an explicit label on the group. ## A practical rule Group what a sighted user perceives as **one thing with one action**, and keep separate anything that has **its own action**. For an email list that means: each row is one element, the row's open action is its double-tap, and its secondary operations are either real buttons outside the group or custom actions on it. Check the result by swiping through the list with VoiceOver and with TalkBack; the number of swipes per row and what each swipe says are the test.

  • A grouped email row contains a Star button. How do you keep starring available to screen-reader users?
    Either move the Star button outside the grouped element so it is its own focus stop, or keep the row grouped and expose starring through `accessibilityActions` with an `onAccessibilityAction` handler, so VoiceOver and TalkBack users pick it from the row's actions. Leaving the button nested inside the group makes it unreachable.
  • Why can a grouped row read awkwardly on iOS even though every child has text?
    When the group has no `accessibilityLabel`, React Native on iOS joins its children's text in view order, including decorative text and whatever order the tree happens to have. For a row that needs specific phrasing, such as an unread marker first, set an explicit label on the group.

saying these in an interview costs you the question

  • accessible={true} on a View makes each child focusable one by one.
  • A Pressable needs accessible={true} before a screen reader can focus it.
  • Grouping a row that contains buttons keeps each button separately reachable.
  • accessible={true} guarantees VoiceOver and TalkBack focus exactly that view.
  • A plain View is an accessibility element by default.