duplicate-name
Mobile validation
Sighted users can often tell similar controls apart from their visual context, for example an “Add to cart” button next to each product. People who use assistive technologies rely on each control's accessible name instead. When different controls share the same name, screen reader users may not be able to tell them apart or predict their results, and voice input users cannot target a specific control by its name. Give each control a unique accessible name that reflects its action or target. You can keep the visible text the same and set a more specific accessible name for assistive technologies. If the visual context alone is not enough to tell the controls apart, make the visible labels unique as well.
Note: Controls that perform exactly the same action, such as two buttons that both open the same settings screen, may share a name.
Pass Patterns
Android
Both buttons show “Add to cart”, and each has a unique contentDescription.
<LinearLayout
...>
<Button
android:layout_width="..."
android:layout_height="..."
android:text="Add to cart"
android:contentDescription="Add to cart (peach)"/>
<LinearLayout
...>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add to cart"
android:contentDescription="Add to cart (banana)"/>
</LinearLayout>
</LinearLayout>Both buttons add different items to the cart, but they have the same name, “Add to cart”.
Text("Favorite color")
Column(modifier = Modifier.selectableGroup()) {
Row(
modifier = Modifier
.selectable(
role = Role.RadioButton,
onClick = { ... },
),
) {
RadioButton(selected = ..., onClick = null)
Text(text = "Orange", modifier = Modifier
.padding(start = 8.dp)
.semantics { contentDescription = "Orange is my favorite color" }
)
}
}
Text("Favorite fruit")
Column(modifier = Modifier.selectableGroup()) {
Row(
modifier = Modifier
.selectable(
selected = ...,
role = Role.RadioButton,
onClick = { ... },
)
) {
RadioButton(selected = ..., onClick = null)
Text(text = "Orange", modifier = Modifier
.padding(start = 8.dp)
.semantics { contentDescription = "Orange is my favorite fruit" }
)
}
}iOS
Both buttons show “Add to cart”, and each has a unique accessibilityLabel.
let addPeachButton = UIButton(type: .system)
addPeachButton.setTitle("Add to cart", for: .normal)
addPeachButton.accessibilityLabel = "Add to cart (peach)"
let addBananaButton = UIButton(type: .system)
addBananaButton.setTitle("Add to cart", for: .normal)
addBananaButton.accessibilityLabel = "Add to cart (banana)"Both buttons show “Add to cart”, and each has a unique accessibilityLabel.
VStack {
Button("Add to cart") {
addToCart(.peach)
}
.accessibilityLabel("Add a peach to the cart")
Button("Add to cart") {
addToCart(.banana)
}
.accessibilityLabel("Add a banana to the cart")
}Cross Platform
Both buttons show “Buy”, and each has a unique semanticsLabel.
child: ListView(
children: [
Card(
child: Column(
children: [
const Text('Peach'),
TextButton(
onPressed: () {},
child: const Text('Buy', semanticsLabel: 'Buy peach'),
),
],
),
),
Card(
child: Column(
children: [
const Text('Banana'),
TextButton(
onPressed: () {},
child: const Text('Buy', semanticsLabel: 'Buy banana'),
),
],
),
),
],
),Both buttons show “Buy”, and each has a unique accessibilityLabel.
<View collapsable={false}>
<Pressable
accessibilityRole="button"
accessibilityLabel="Buy banana"
onPress={ ... }
style={styles.button}
>
<Text>Buy</Text>
</Pressable>
</View>
<View collapsable={false}>
<Pressable
accessibilityRole="button"
accessibilityLabel="Buy peach"
onPress={ ... }
style={styles.button}
>
<Text>Buy</Text>
</Pressable>
</View>Fail Patterns
Android
Both buttons add different items to the cart, but they have the same name, “Add to cart”.
<LinearLayout
...>
<Button
android:layout_width="..."
android:layout_height="..."
android:text="Add to cart"/>
<LinearLayout
...>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add to cart"/>
</LinearLayout>
</LinearLayout>Both buttons add different items to the cart, but they have the same name, “Add to cart”.
Text("Favorite color")
Column(modifier = Modifier.selectableGroup()) {
Row(
modifier = Modifier
.selectable(
role = Role.RadioButton,
onClick = { ... },
),
) {
RadioButton(selected = ..., onClick = null)
Text(text = "Orange", modifier = Modifier
.padding(start = 8.dp)
)
}
}
Text("Favorite fruit")
Column(modifier = Modifier.selectableGroup()) {
Row(
modifier = Modifier
.selectable(
selected = ...,
role = Role.RadioButton,
onClick = { ... },
)
) {
RadioButton(selected = ..., onClick = null)
Text(text = "Orange", modifier = Modifier
.padding(start = 8.dp)
)
}
}iOS
Both buttons add different items to the cart, but they have the same name, “Add to cart”.
let addPeachButton = UIButton(type: .system)
addPeachButton.setTitle("Add to cart", for: .normal)
let addBananaButton = UIButton(type: .system)
addBananaButton.setTitle("Add to cart", for: .normal)Both buttons add different items to the cart, but they have the same name, “Add to cart”.
VStack {
Button("Add to cart") {
addToCart(.peach)
}
Button("Add to cart") {
addToCart(.banana)
}
}Cross Platform
Both buttons add different items to the cart, but they have the same name, “Buy”.
child: ListView(
children: [
Card(
child: Column(
children: [
const Text('Peach'),
TextButton(
onPressed: () {},
child: const Text('Buy'),
),
],
),
),
Card(
child: Column(
children: [
const Text('Banana'),
TextButton(
onPressed: () {},
child: const Text('Buy'),
),
],
),
),
],
),Both buttons add different items to the cart, but they have the same name, “Buy”.
<View collapsable={false}>
<Pressable
accessibilityRole="button"
accessibilityLabel="Buy"
onPress={ ... }
style={styles.button}
>
<Text>Buy</Text>
</Pressable>
</View>
<View collapsable={false}>
<Pressable
accessibilityRole="button"
accessibilityLabel="Buy"
onPress={ ... }
style={styles.button}
>
<Text>Buy</Text>
</Pressable>
</View>Try It Yourself
Using a screen reader
New to screen reader testing, or need a refresher?
Review this article first: Practical guides for using screen readers
- Turn on VoiceOver on iOS, or TalkBack on Android.
- Swipe right or left through the interactive elements on the screen.
- Listen for different controls that are announced with the same name. Pay attention to repeated controls, such as buttons in list items, and icon-only buttons.
Expected results: Each control that performs a different action has a unique name, for example “Add a peach to the cart, button”.
Actual results: Different controls are announced with the same name, for example “Add to cart, button” for every product.
Using voice input
New to voice input testing, or need a refresher?
Review this article first: Practical guides for using voice input
- Turn on Voice Control on iOS, or Voice Access on Android.
- Say “Show names” on iOS, or “Show labels” on Android.
- Look for different controls that show the same name.
Expected results: Each control that performs a different action shows a unique name, so it can be activated by speaking it.
Actual results: Several controls show the same name, so it cannot be used to target a specific one.
FAQ
Why is this issue marked as Minor?
Users can still reach and activate the controls, but they may need extra time, or extra context from the surrounding content, to work out which control does what. They may also activate the wrong one. Most tasks remain possible, so it is rated minor.
How does this issue relate to 4.1.2 Name, Role, Value
WCAG 4.1.2 requires each user interface component to expose an accessible name and role, and to convey its states, properties, and value to assistive technologies. When different controls share the same accessible name, the name does not distinguish their action or target. Assistive technology users, including screen reader and voice input users, cannot reliably identify or activate the intended control.
Provide a unique accessible name for every control that triggers a different action or operates on a different item to meet the intent of 4.1.2. You can keep the visible text and supply a more specific accessible name for assistive technologies when needed. If visual context alone does not distinguish controls, make the visible labels unique as well.
Note: Controls that perform exactly the same action, such as two buttons that both open the same settings screen, may share a name.
Standards and Regulations
| Standard | Success Criterion | Reference |
|---|---|---|
| WCAG 2.2 | 4.1.2 Name, Role, Value (A) | For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to assistive technologies. |
| EN 301 549 | 11.4.1.2 Name, Role, Value | Same as the WCAG text. |
| Section 508 | 1194.21(d) | Sufficient information about a user interface element including the identity, operation and state of the element shall be available to assistive technology. When an image represents a program element, the information conveyed by the image must also be available in text. |