Advent of iOS Accessibility
Advent of iOS Accessibility
Starting something new: The Advent of iOS Accessibility. Twenty-four days of exploring some of the most common accessibility issues I’ve encountered, how to identify them, and—most importantly—how to fix them. Hope you enjoy the series!
Day 1
One of the accessibility issues I see more often in iOS apps, believe it or not, is unlabelled elements. This happens especially for buttons with an icon but no title. In those cases, you need to configure an accessibility label manually.
Day 2
Some recommendations for improving your accessibility labels: don’t add the element type, avoid redundancy and verbosity, localize…
Day 3
Anything representing a heading in the app should have the header trait. It allows for a faster way of exploring a screen and quickly jumping to the part of the app you are interested in. Screens should also start with a header.
Day 4
Important information is often conveyed visually through icons, badges, or progress bars… These details can easily be overlooked. Please make sure they’re part of your UI’s components' accessibility labels or values for a more inclusive experience.
Day 5
Images should either be decorative or have a proper accessibility label or alt text that describes them. If they’re decorative you can make it so they get skipped by assistive tech so it doesn’t get in the way of the experience.
Quick clarification on this one. It is probably not the best example of decorative images. I think these images should have alt text. But in my experience, most APIs won’t give you one for movie posters, music artwork, and things like that… And the point is that a random name just adds noise.
And another nuance. VoiceOver has a feature called Image Explorer. VoiceOver can recognise text, people and objects in images. So if you think that users can get value with this feature, you might want to consider exposing the image then.
Oh! And avoid images of text please!
Day 6
With regular buttons from UIKit or SwiftUI, you are all set. With complex views, headings, or table/collection view cells that, when selected, bring the user somewhere else in the app or perform an action, you’ll have to add the button accessibility trait yourself to convey users that it is an interactive component.
Day 7
Grouping elements when it makes sense can make a huge impact on easing navigation with some assistive technologies like VoiceOver, Switch Control, or Full Keyboard Access. It also helps on reducing redundancy.
In UIKit, this process consists of three steps:
- Setting the parent view as an accessible element: https://iosdev.space/@dadederk/109693895401281036
- Configure relevant accessibility label, value, traits and hints on the parent view: https://iosdev.space/@dadederk/109806337876803727
- If there are secondary actions within the grouped view, configure custom actions: https://iosdev.space/@dadederk/1097016
In SwiftUI, it might be as simple as using the .accessibilityElement(children:) modifier with the .combine accessibility child behaviour: https://iosdev.space/@dadederk/109932750048041110 If that doesn’t quite work as expected, try to tweak the internal views. If not, you can fall back to UIKit’s three step process.
Day 8
If a view has isAccessibilityElement to true, assistive tech won’t look for any of its subviews. That means that if there are any buttons inside, they won’t be accessible. You can add custom actions to be able to ‘interact’ with them.
Day 9
If you have interactions that are hidden or require complex gestures to be performed or that may conflict with VoiceOver, you need to provide alternative ways of executing these actions. Custom actions can help a lot of times, but not always.
Day 10
Toggles or UISwitches are often found separated from the label that precedes (and describes) them; with an unclear label; missing a value, trait, or hint; or even not being actionable at all.
Day 11
Have you ever seen VoiceOver randomly focusing on elements of the previous view when presenting a custom modal view? That can be fixed by letting the system know that the presented view is modal in terms of accessibility.
Day 12
Sometimes we may fail to update users of things changing on the screen in a perceivable way. Toasts and similar should be announced. We may want to make clear that some content on the screen changed or to update on a task’s progress.
Day 13
Sometimes, you may want to create a custom component, even if there is a similar one in UIKit or SwiftUI because you want to style it in a way that the default one won’t let you. Or add extra functionality. That’s fine, but please take into account that you may need a bit of extra work to make it accessible.
Day 14
iOS and Xcode provide a wide variety of tools and options to deal with color, and help us providing good color contrast ratios. From system colors that automatically support Increase Contrast, to high contrast (and light and dark mode) color asset variants, automatic checks with the Audit feature in the Accessibility Inspector, and even a built-in contrast calculator.
Day 15
Touch target sizes are recommended to be at least 44 x 44 points for better usability. Buttons in the navigation bar (especially when not using nav bar button items), dismiss buttons, and custom toolbars, are common examples that often fall below this size.
Day 16
A reminder that the more modes we use to convey important information, the more likely it is that all users will perceive it. Consider a combination. of color, icons, messages, sound, haptics, animations, etc.
Day 17
Check the traversal order of elements in your app. Sometimes the default top-left to bottom-right order might not be the most logical one. Sometimes you may consciously want to tweak the order. Other times, grouping is the answer.
If you want to find out more, we had an interesting conversation in Bluesky with Paul J. Adam, on the nuances of how to implement this.
Day 18
When building custom components, or if not relying on UIControl’s attributes to configure state, it can be easy to forget to specify the right accessibility traits. These are indispensable for a good experience with VoiceOver, Switch Control, Voice Control, Full Keyboard Access…
Day 19
Accessibility labels might not be the best input labels, used for example to find or interact with elements with Voice Control or Full Keyboard Access. In those cases, you can provide accessibility user input labels.
To know more about accessibilityUserInputLabels checkout: “Improving Accessibility: Voice Control” by Bas Broek
Day 20
There is an option for the user to request an experience with Reduce Motion, and we should honor it. If your app has animations, make sure to check if the user has this setting on. Here are three examples where Apple does a great job.
You can support Reduce Motion in UIKit and SwiftUI.
Day 21
There are a few accessibility settings you can check for, or get notifications in case these preferences change. This is especially important when developing custom components as they will mostly work with UIKit and SwiftUI controls.
Checkout UIKit’s Accessibility Capabilities and SwiftUI’s Accessibility environment variables.
Day 22
Make sure you support Dynamic Type up to the largest text size available. Take into account that there are five extra accessibility sizes available from the Accessibility Settings. It can make a huge difference for lots of users.
Day 23
Sometimes your UI will just not optimally scale for large text sizes. Simple changes, for accessibility sizes, like composing elements vertically instead of horizontally, reducing the number of columns, and allowing more lines of text, can do the trick most times.
Day 24
Test manually. Familiarise yourself with different assistive technologies. I find it useful to start with VoiceOver but check out Voice Control, Full Keyboard Access, and others… Remove friction, configuring shortcuts can help. Happy festive season everyone!
Happy festive season everyone!
Thanks for following the series till the end! For more accessibile iOS apps in 2025!
You can also follow the series in: