Conflicting Traits

Link to Conflicting Traits copied to clipboard

Platform Guideline Impact - Critical

Views should not have conflicting accessibility traits.

Impact

People using VoiceOver and Switch Control are most impacted. Conflicting traits may cause navigation gestures in assistive technology to become unresponsive. A control's role may be relayed to the user improperly because of a mismatched trait.

Confirmation

  1. Turn on VoiceOver
  2. Focus the element
  3. One of the following will happen:
    • Inaccessible: VoiceOver will announce two conflicting roles (such as "Button" and "Link")
    • Inaccessible: A VoiceOver navigation gesture will no longer work (such as using "Heading" and "Adjustable" together)
    • Accessible: All roles make sense, and navigation gestures work as intended.

How to Fix

An improper selection of Accessibility Traits causes an issue found by this rule. Read more on Accessibility Traits in Apple's documentation for UIKit or SwiftUI.

UIKit

In storyboard:

  1. Select the accessibility element with conflicting accessibility traits.
  2. Ensure that the Inspector Panel is visible.
  3. Select the Identity Inspector.
  4. Under "Accessibility", there is a category called "Traits". Unselect the checkbox of the Accessibility Trait that is conflicting.

In code:

  • Remove the conflicting accessibility trait. For example, a button may have the following Accessibility Traits:
button.accessibilityTraits = [.button, .link]

The button should only have one of them, depending on the button's context. In this case, the conflicting one was "link". To use a button as a link, remove the button trait for the desired behavior.

button.accessibilityTraits = .link

SwiftUI

While updating accessibility traits, ensure each trait reflects the proper usage of the control. For example, if a button mimics a link, you remove the default 'button' accessibility trait and add the 'link' trait.

    var body: some View {
        Button(action: { openLink() },
               label: {
            Text("Visit this Site!").padding()
        })
        .accessibility(addTraits: .isLink)
        .accessibility(removeTraits: .isButton)
    }

React Native

This rule is not expected to fail on React Native views. React Native only allows one element added to the accessibilityRole property.

Tip: To provide a good experience and follow best practices, utilize the accessibilityRole property with the value which accurately describes the element's expected behavior. Example: adjust a button's accessibilityRole to link, when it's behaving as a link.

<Button
  title={'Learn more about axeDevTools'}
  accessible={true}
  accessibilityElementsHidden={false}
  accessibilityRole='link'
  onPress={goToLink}
/>