The Business Case for Accessibility

15% of the population has a disability. Ignoring a11y ignores a huge market and opens you to lawsuits (ADA). It's also just the right thing to do. Accessibility (often abbreviated as a11y) is not optional—it's essential for inclusive design.

Market size:

  • 1 billion people: Worldwide have some form of disability
  • 15% of users: Potential customers you're excluding without a11y
  • $8 trillion: Combined annual disposable income of people with disabilities
  • Legal requirements: ADA (Americans with Disabilities Act) compliance mandatory in many regions

Business benefits:

  • Increased Market Share: Reach more potential users
  • Better UX for All: Accessible apps are better for everyone
  • Legal Protection: Avoid costly lawsuits and penalties
  • Brand Reputation: Shows commitment to inclusion
  • SEO Benefits: Better semantic HTML improves search rankings
Accessibility isn't just for people with disabilities—it makes your app better for everyone.

VoiceOver Basics: Understanding Screen Reading

VoiceOver reads the screen to blind users. Navigation is linear (swipe left/right). Elements must be reachable and clear. VoiceOver is iOS's built-in screen reader:

How VoiceOver works:

  • Linear Navigation: Users swipe left/right to move between elements
  • Text-to-Speech: Reads element labels and content aloud
  • Gesture Support: Double-tap to activate, swipe to navigate
  • Rotor Navigation: Jump by headings, links, buttons, etc.
  • Custom Gestures: Users configure preferred gestures

Key concepts:

  • Accessibility Elements: What VoiceOver can read
  • Accessibility Tree: The structure VoiceOver navigates
  • Reading Order: The sequence in which elements are read
  • Focus: Which element is currently selected

Understanding VoiceOver's linear navigation is crucial. Unlike sighted users who can see the entire screen, VoiceOver users experience your app sequentially. This makes logical ordering and clear labels essential.

Labels, Traits, and Hints: Making Elements Understandable

Label: "Play". Trait: "Button". Hint: "Double tap to start music". Configure these in Xcode Identity Inspector or code. These three properties make your UI accessible:

Accessibility Label:

  • Purpose: Identifies the element to VoiceOver
  • Best Practices: Be concise but descriptive
  • Examples: "Play button", "Close menu", "Save profile"
  • Code: button.accessibilityLabel = "Play music"

Accessibility Traits:

  • Purpose: Describes element type and behavior
  • Common Traits: .button, .link, .header, .selected, .image
  • Multiple Traits: Can combine traits (e.g., .button + .selected)
  • Code: button.accessibilityTraits = .button

Accessibility Hints:

  • Purpose: Explains what happens when activated
  • Best Practices: Only when the action isn't obvious
  • Examples: "Double tap to open", "Swipe up to dismiss"
  • Code: button.accessibilityHint = "Double tap to start music"

In SwiftUI, use modifiers like .accessibilityLabel(), .accessibilityAddTraits(), and .accessibilityHint(). UIKit uses the accessibilityLabel, accessibilityTraits, and accessibilityHint properties.

Grouping Elements: Logical Content Organization

Don't make VoiceOver read "Song Title", swipe, "Artist", swipe. Group them so it reads "Song Title by Artist" in one go. Grouping related elements improves navigation efficiency:

Why grouping matters:

  • Efficiency: Reduces number of swipes needed
  • Context: Related information stays together
  • Clarity: Makes content relationships clear
  • Better UX: Faster navigation improves user experience

How to group:

  • SwiftUI: Use .accessibilityElement(children: .combine)
  • UIKit: Set accessibilityElementsHidden on parent, create custom label
  • Combine Labels: Merge related labels into one meaningful description

Example scenarios:

  • List Items: Group title, subtitle, and metadata
  • Cards: Combine image, title, and description
  • Forms: Group label and input field
  • Buttons: Group icon and text

Test your groupings: Enable VoiceOver and navigate your app. If you find yourself swiping through multiple elements that should be together, group them.

Custom Actions: Enhancing Complex Interactions

For complex items (e.g., mail list item), add "Rotor Actions" like Delete or Archive so users don't need to find tiny buttons. Custom actions make complex interfaces accessible:

When to use custom actions:

  • Complex Items: List items with multiple actions
  • Hidden Controls: Actions accessible via swipe
  • Multiple Options: When one element has multiple functions
  • Simplified Navigation: Reduce need for precise gestures

Implementing custom actions:

  • SwiftUI: Use .accessibilityAction(named: "Delete")
  • UIKit: Implement accessibilityCustomActions property
  • Actions Array: Provide array of UIAccessibilityCustomAction objects

Rotor navigation:

  • Rotor: Accessibility feature to jump by element type
  • Custom Rotors: Create custom categories (e.g., "Actions", "Links")
  • Usage: Rotate two fingers on screen to change rotor category

Custom actions appear in VoiceOver's action menu, accessible via the rotor. This allows users to perform actions without navigating to tiny buttons, dramatically improving usability for complex interfaces.

Testing Accessibility: Ensuring Your App Works

Enable the Accessibility Inspector in Xcode. Or triple-click the side button on your iPhone and try to use your app with eyes closed. Testing is crucial for accessibility:

Accessibility Inspector (Xcode):

  • Visual Tree: See the accessibility hierarchy
  • Element Details: View labels, traits, hints for each element
  • Warnings: Automatic detection of common issues
  • Simulator Testing: Test VoiceOver in iOS Simulator

Device Testing:

  • Enable VoiceOver: Settings → Accessibility → VoiceOver
  • Physical Device: Best for real-world testing
  • Blindfold Test: Try using your app with VoiceOver only
  • Expert Users: Test with actual VoiceOver users

Automated Testing:

  • XCUITest: Test accessibility properties programmatically
  • Continuous Integration: Run accessibility tests in CI/CD
  • Tools: Accessibility Scanner, axe DevTools

Testing with VoiceOver is eye-opening. You'll discover issues you never noticed visually. Make it part of your development workflow, not an afterthought.

Dynamic Type Support: Accommodating Different Vision Needs

Ensure your layouts adapt when fonts scale up. A11y isn't just for blind users; it's for low vision too. Dynamic Type is iOS's system-wide text scaling feature:

Why Dynamic Type matters:

  • Low Vision Users: Need larger text to read comfortably
  • Age-Related Vision: Vision changes with age
  • Device Size: Users customize text size per device
  • Legal Requirement: Required for accessibility compliance

Supporting Dynamic Type:

  • Use System Fonts: SF Pro automatically scales
  • Text Styles: Use .title, .body, .caption instead of fixed sizes
  • Flexible Layouts: Designs must adapt to larger text
  • Test Scaling: Check your app at all text size settings

SwiftUI implementation:

  • Use .font(.body) instead of fixed sizes
  • Leverage @ScaledMetric for spacing
  • Test with .environment(.sizeCategory, .accessibilityExtraExtraLarge)

UIKit implementation:

  • Use UIFont.preferredFont(forTextStyle:)
  • Listen for UIContentSizeCategory.didChangeNotification
  • Use constraint priorities for flexible layouts

Test your app at all Dynamic Type sizes, including the extra large accessibility sizes. Many apps break at larger sizes—don't let yours be one of them. Proper Dynamic Type support makes your app usable by millions more users.

Accessibility isn't a feature—it's a fundamental requirement for inclusive app design. Build it in from the start, not as an afterthought.