# Conflicting Traits (Mobile)

> In iOS apps, an element must not combine accessibility traits that contradict each other.

Source: https://knowledge.evinced.com/mobile/mobile-validations/conflicting-traits

An element must not combine iOS accessibility traits that contradict each other.

On iOS, accessibility traits tell VoiceOver and Switch Control what an element is and how it behaves, for example `.button`, `.link`, or `.header`. When an element has traits that contradict each other, assistive technologies may announce two incompatible roles, expose the wrong action, or ignore a gesture. Choose the one trait that best matches the element's behavior, or split the element into separate components, so each has a single, clear role.

**Note:** This validation applies to iOS only. Accessibility traits are an iOS concept, and Android elements expose a single role, so there are no Android or cross-platform examples.

These trait combinations conflict with each other:

| When | Is combined with | The user |
| --- | --- | --- |
| `.adjustable` | `.causesPageTurn` | encounters conflicting event handlers |
| `.adjustable` | `.header` | cannot navigate to this heading with the rotor |
| `.allowsDirectInteraction` | `.button` | cannot activate the component |
| `.allowsDirectInteraction` | `.keyboardKey` | cannot activate using the keyboard key |
| `.allowsDirectInteraction` | `.link` | cannot activate the link |
| `.allowsDirectInteraction` | `.searchField` | cannot activate the search field |
| `.allowsDirectInteraction` | `.toggleButton` | cannot activate the toggle button |
| `.button` | `.link` | cannot tell whether activation will leave the app |
| `.button` | `.searchField` | cannot tell what will happen on activation |
| `.link` | `.searchField` | cannot tell what will happen on activation |

## Pass Patterns

### iOS

**UIKit**

The tappable label has a single trait, `.button`, that matches its behavior.

```swift
let submitLabel = UILabel()
submitLabel.text = "Submit"
submitLabel.isUserInteractionEnabled = true
submitLabel.accessibilityTraits = .button
submitLabel.addGestureRecognizer(
    UITapGestureRecognizer(target: self, action: #selector(handleTap))
)
```

**SwiftUI**

The tappable text has a single trait, `.isButton`, that matches its behavior.

```swift
Text("Submit")
    .onTapGesture { submit() }
    .accessibilityAddTraits(.isButton)
```

## Fail Patterns

### iOS

**UIKit**

The label has both the `.button` and `.link` traits, so users cannot tell whether activating it will leave the app.

```swift
let submitLabel = UILabel()
submitLabel.text = "Submit"
submitLabel.isUserInteractionEnabled = true
submitLabel.accessibilityTraits = [.button, .link]
submitLabel.addGestureRecognizer(
    UITapGestureRecognizer(target: self, action: #selector(handleTap))
)
```

**SwiftUI**

The text has both the `.isButton` and `.isLink` traits, so users cannot tell whether activating it will leave the app.

```swift
Text("Submit")
    .onTapGesture { submit() }
    .accessibilityAddTraits([.isButton, .isLink])
```

## 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](https://knowledge.evinced.com/a11y-essentials/practical-guides-for-using-screen-readers)

1.  Turn on VoiceOver.
2.  Swipe right or left to move to the element.
3.  Listen to the roles announced after its name, and try to activate it with a double tap.

**Expected results:** VoiceOver announces a single role that matches the element's behavior, and the element responds as expected.

**Actual results:** VoiceOver announces more than one role, such as both “*button*” and “*link*”, or the element does not respond to the expected gesture.

### Using developer tools

1.  In Xcode, open **Xcode > Open Developer Tool > Accessibility Inspector**, select the simulator or device, and point at the element.
2.  Check the element's **Traits**.

**Expected results:** The **Traits** contain no conflicting combination from the table above.

**Actual results:** The **Traits** contain a conflicting combination, such as **Button** and **Link**.

## FAQ

**Why is this issue marked as Critical?**

Conflicting traits can make VoiceOver and Switch Control announce the wrong role, ignore gestures, or block activation altogether. Users may be unable to complete a task, or may be sent somewhere they did not expect, so it is rated critical.

**How does this issue relate to 4.1.2 Name, role, value?**

SC 4.1.2 requires the role of every user interface component to be programmatically determinable. When an element exposes traits that contradict each other, assistive technologies cannot determine a single, consistent role, and may not be able to operate the element reliably.

**How does this issue relate to 1.3.1 Info and Relationships?**

Conflicting traits relate to 1.3.1 because information and relationships must be programmatically determinable and accurate. When one element exposes multiple, incompatible `traits`, assistive technology cannot determine a single `role` or relationship.

This can cause VoiceOver or Switch Control to announce different roles, expose the wrong action, or ignore a gesture. That breaks the programmatic mapping between what is presented and how it is structured.

To meet 1.3.1, assign one `trait` that matches the element’s behavior, or split it into separate components so each has a single, clear `role`.

## Standards and Regulations

| Standard | Success Criterion | Reference |
| --- | --- | --- |
| WCAG 2.2 | [4.1.2 Name, Role, Value](https://www.w3.org/TR/WCAG22/#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. |
| WCAG 2.2 | [1.3.1 Info and Relationships](https://www.w3.org/TR/WCAG22/#info-and-relationships) (A) | Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text. |
| EN 301 549 | [11.4.1.2 Name, Role, Value](https://www.etsi.org/standards/etsi-301-549) | Same as the WCAG text. |
| EN 301 549 | [11.1.3.1 Info and Relationships](https://www.etsi.org/standards/etsi-301-549) | Same as the WCAG text. |

## Personas impacted by this issue

-   [Screen Reader](https://knowledge.evinced.com/a11y-essentials/personas#screen-reader)
-   [Voice Input](https://knowledge.evinced.com/a11y-essentials/personas#voice-input)

## Related Issues

-   [conflicting-state-in-name](https://knowledge.evinced.com/mobile/mobile-validations/conflicting-state-in-name)
-   [conflicting-type-in-label](https://knowledge.evinced.com/mobile/mobile-validations/conflicting-type-in-label)
-   [interactable-role](https://knowledge.evinced.com/mobile/mobile-validations/interactable-role)
