DEV Community

Diana Hernández
Diana Hernández

Posted on

A11y in SwiftUI: Grouping

Let's group elements accessibly in SwiftUI

Welcome to this series of articles about accessibility in SwiftUI!

Over the next few weeks, we'll explore different aspects of A11y to create truly inclusive applications. In this first article, we'll focus on a fundamental technique: grouping elements.

The Scenario: A Book List 📚

Imagine you're developing a book app. You have a list where each item shows:

🌆 A book cover
📗 The title
📝 The author
📆 The publication year
⭐️ A star rating

Sounds simple, right? But when we activate VoiceOver, things get complicated...

Houston, We Have a Problem 🚨

screenshot of the app with every UI element as A11y element

If we don't configure accessibility, VoiceOver will treat each UI element as an independent item.

This means our users will have to navigate through five different elements to understand the information for a single book.
Not the best experience, right?

The Key Question: What's Really Important? 🤔

Before we start coding, we should ask ourselves some questions:

  • Does the cover image provide unique information that isn't in the text?
  • Do we need VoiceOver to read decorative emojis?
  • How does the user visually perceive this information?

The answer leads us to a conclusion: visually, we perceive each book as a unit, not as separate elements.
Let's make the VoiceOver experience reflect this!

Solution 1: The Quick Path ⚡️
The most direct way to solve this is to group everything into a single accessible element:

BookView(book: book)
    .accessibilityElement()
    .accessibilityLabel("\(book.title) written by \(book.author) in \(book.year), \(book.stars) out of 5")
Enter fullscreen mode Exit fullscreen mode

Solution 2: The Granular Approach 🎯
For more complex views, we can opt for a more structured approach:

struct BookView: View {
    let book: Book

    var body: some View {
        HStack {
            Image(book.image)
                .accessibilityHidden(true)  // The image is decorative

            VStack {
                Text(book.title)
                // The default label works well here

                Text(book.author)
                    .accessibilityLabel("written by \(book.author)")

                Text("📆 \(book.year)")
                    .accessibilityLabel("in \(book.year)")

                RatingView(rating: book.stars)
                    .accessibilityLabel("\(book.stars) stars out of 5")
            }
            .accessibilityElement(children: .combine)
            // Combines all labels into a single fluid reading
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

The Result: A Unified Experience ✨

Screenshot of the app with all the information regarding one book as an unique A11y element

Now, VoiceOver treats each book as a coherent unit, offering a much more natural and efficient experience.
Which One to Choose? 🤷‍♀️

Solution 1: Perfect for simple and straightforward components
Solution 2: Ideal for complex views where you need more control over each element

Conclusion and Next Steps 🎯

Accessibility isn't an extra, it's a fundamental necessity. In this article, we've seen how proper grouping of elements can significantly improve the experience for users who rely on VoiceOver.

In the next article in the series, we'll explore how to handle traits in SwiftUI. Don't miss it!

Did you find this article helpful? Do you have any doubts, questions, or advice about accessibility in SwiftUI?
Drop by BlueSky and let's talk!


🗒️ This article is an English translation of my original Spanish article: A11y en SwiftUI: Agrupando que es gerundio

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Sentry mobile image

App store rankings love fast apps - mobile vitals can help you get there

Slow startup times, UI hangs, and frozen frames frustrate users—but they’re also fixable. Mobile Vitals help you measure and understand these performance issues so you can optimize your app’s speed and responsiveness. Learn how to use them to reduce friction and improve user experience.

Read full post →

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay