Improve App Accessibility in Flutter for Better User Experience
Tags: flutter, ux, tutorial, programming
Published: 2023-03-30 19:34:00

Enter Accessibility (A11y)! Many developers ignore it, some are even unaware of it, but app accessibility is as important as any other feature. Your audience may include people who do not use the internet the same was as others, which could make it challenging or even impossible to use your beautifully crafted Flutter apps.

According to the [World Health Organization](https://www.who.int/news-room/fact-sheets/detail/disability-and-health), there are over 1 billion people with disabilities around the world. This can make it challenging to carry out daily tasks and perform actions that others often take for granted. In our context as Flutter developers, we want to make sure that everyone can interact with digital services, [apps](https://code.pieces.app/blog/flutter-app-python-backend), [games](https://code.pieces.app/blog/flutter-game-pong-game-flame), etc.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7u1xsnxvgt7ytoijua2a.png "A grid of disabilities that read: vision, hearing loss, cognitive, neurological, mobility, and motor impairment.")
‍

[Building accessible apps](https://code.pieces.app/blog/accessibility-in-web-development-wai-aria-and-implementation) should be one your main goals. App accessibility is about building products that are accessible to everyone, no matter their abilities. Making your app accessible may also help to broaden your user base, as allowing more people to engage with your application increases your DAU count.

Flutter is a cross-platform framework that makes it possible to reach millions of users across the world. By implementing accessibility options in a friendly and consistent way, we can make sure that developers— as well as users— have the same experience no matter which platform they are using.

Flutter accessibility is pretty simple, as it's designed to be accessible out-of-the-box while providing first-class framework support for solving accessibility problems by adding to what the underlying operating system offers.

We’ll see how we can tackle some of these common app accessibility problems mentioned below in Flutter and provide a better experience for everyone.

## Text Scaling

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7kakag996xatab94njdt.gif "A gif of random text increasing and decreasing.")

People who have vision problems may find it difficult to read text in your app when it's the default size. They often rely on screen readers or enlarging the text with the accessibility options on their devices. Be aware of this **text scale factor** to make sure that the text within your app scales properly based on accessibility settings.

In Flutter app development, if you’re using a _Text widget_ to display text, then the changing text size calculations are handled by the widget itself. It has a textScaleFactor property which is multiplied by the set/default font size to calculate the text's new font size.

The Flutter _textScaleFactor_ is obtained from the _MediaQuery.of(context).textScaleFactor_, which represents the _textscaleFactor_ set by the underlying operating system or user through accessibility options. By default, it’s 1.0.

For example, if the _textscaleFactor_ is 1.5, the text will be 50% larger than the specified font size.

Note that if you’re using a _RichText_ Flutter widget, it won't support automatic text scaling. You’ll need to explicitly pass the _textscaleFactor_ from the _MediaQuery_ to the _RichText_ widget’s _textscaleFactor_ parameter.

Finally, always make sure your UI layout is proper for scaling text. If your UI doesn’t look good or is almost useless above a certain font size, then you need to update your layout. For more information, check out this very interesting article that discusses [Restricting system textScaleFactor](https://iiro.dev/restricting-system-text-scale-factor/).

Be aware that limiting text scaling may create problems for some users, so choose carefully!

**Note**: Contrast is the difference in [luminance](https://en.wikipedia.org/wiki/Luminance) or [color](https://en.wikipedia.org/wiki/Color) that makes an object (or its representation in an image or display) distinguishable. — [Wikipedia](https://en.wikipedia.org/wiki/Contrast_(vision))

The **contrast ratio (CR)** is defined as the [ratio](https://en.wikipedia.org/wiki/Ratio) of the luminance of the brightest shade to that of the darkest shade that the system is capable of producing. This ratio is within a range of 1 to 21 (commonly written as 1:1 to 21:1), where increasing numbers mean higher contrast. — Wikipedia

## Contrast

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/25y1mp3agrf3bpkj7c04.gif "Random text changing in color and contrast.")

People with vision impairments may also face issues using your app if there’s not enough contrast between different parts of your app. Many visual impairments cause issues with reading text at a low contrast. Even people with normal vision will face this issue if there’s not enough contrast between text and its background.

The W3C recommends the following contrast ratios (CR) depending on the situation:

- 4.5:1 — If text is less than 18 points (24px) if not bold, and less than 14 pt (18px) if bold.
- 3:1 — If text is at least 18 pt if not bold and at least 14 pt if bold.

The following image shows you different contrast levels for text with its background. The example on the left has a CR of 1.96:1, below the accessibility standard, which makes it hard to read. The other two have an acceptable CR, so we can easily read the text.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q09xehl5wz1ett00wgxu.png "An image containing three rectangles in a row. One shows low contrast with a light blue background and white text. The second rectangle shows moderate contrast which has a medium blue as the background and white text and the third rectangle has a dark blue background with white text making it high contrast.")

As Flutter follows Material Design guidelines, most parts of your apps will have high enough contrast between text and their background unless you’ve added custom theming, in which case you need to make sure the CR is high enough.

You can use online tools like [contrast-checker](https://webaim.org/resources/contrastchecker/) and [contrast-ratio](https://contrast-ratio.com/) to see if the CR of your colors meets app accessibility standards.

Also, some users may prefer a higher CR than the default. They can turn on this option through the accessibility settings on their device.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cvhgp3r8jzsbyd53e1qs.jpg "A screenshot of the settings view showing "Increase Contrast" turned on.")

In your app, you can add a check for this option through the highContrast property of _MediaQuery_. Based on the result, update your background colors to provide higher contrast.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oo59z6tusx32qktmsgmo.png "A code snippet with Dart code.")
[Save to Pieces](https://shared.code.pieces.app/?compressed=eyJiYXNlIjoiaHR0cHM6Ly9yYW1hbi5waWVjZXMuY2xvdWQiLCJzaGFyZSI6IjE3ZTUwMWQ3LThmZWQtNGI4Yy1iYmQ4LTg3YmM2N2RlMzJlYSIsImFzc2V0IjoiYWQ0ZDdhYTctZTczYi00ZTEzLWJjODYtNWI0ZmNhODNjNTYwIiwibmFtZSI6IlJhbWFuIEh1bmRhbCIsInRpdGxlIjoiQ2hlY2tpbmcgQWNjZXNzYmlsaXR5IFNldHRpbmdzIiwiZGVzY3JpcHRpb24iOiJDaGVja2luZyBhY2Nlc3NiaWxpdHkgc2V0dGluZ3MiLCJ1c2VyIjp7InNjaGVtYSI6eyJtaWdyYXRpb24iOjAsInNlbWFudGljIjoiTUFKT1JfMF9NSU5PUl8wX1BBVENIXzEifSwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hL0FBVFhBSnctZ2N3ZGZ1c1B2bVJidTFBMUFmb05qcEpPbVRNTnRvVnpXVzB2PXM5Ni1jIiwiZW1haWwiOiJyYW1hbkBwaWVjZXMuYXBwIiwiY3JlYXRlZCI6eyJ2YWx1ZSI6IjIwMjItMDQtMzBUMTg6Mjc6NDMuNTUxWiIsInJlYWRhYmxlIjoiMTEgbW9udGhzIGFnbyJ9LCJ1cGRhdGVkIjp7InZhbHVlIjoiMjAyMi0wNS0yNVQxNzowOTo1MC45MjlaIiwicmVhZGFibGUiOiIxMCBtb250aHMgYWdvIn0sImlkIjoiZTVjNjg3OWQtMTUyNi00MTY4LTk1YTItYmFiYmVlNzU5M2Q0IiwibmFtZSI6IlJhbWFuIEh1bmRhbCIsImFlc3RoZXRpY3MiOnsidGhlbWUiOnsiZGFyayI6dHJ1ZX0sImZvbnQiOnsic2l6ZSI6MTZ9fSwiYWxsb2NhdGlvbiI6eyJzY2hlbWEiOnsibWlncmF0aW9uIjowLCJzZW1hbnRpYyI6Ik1BSk9SXzBfTUlOT1JfMF9QQVRDSF8xIn0sImlkIjoiZTVjNjg3OWQtMTUyNi00MTY4LTk1YTItYmFiYmVlNzU5M2Q0IiwidXNlciI6ImU1YzY4NzlkLTE1MjYtNDE2OC05NWEyLWJhYmJlZTc1OTNkNCIsInVybHMiOnsiYmFzZSI6eyJzdGF0dXMiOiJSVU5OSU5HIiwidXJsIjoiaHR0cHM6Ly91c2VyLWU1YzY4NzlkLTE1MjYtNDE2OC05NWEyLWJhYmJlZTc1OTNkNC1maGNtYmhla2xxLXVjLmEucnVuLmFwcCJ9LCJpZCI6eyJzdGF0dXMiOiJSVU5OSU5HIiwidXJsIjoiaHR0cHM6Ly9lNWM2ODc5ZC0xNTI2LTQxNjgtOTVhMi1iYWJiZWU3NTkzZDQucGllY2VzLmNsb3VkIn0sInZhbml0eSI6eyJzdGF0dXMiOiJSVU5OSU5HIiwidXJsIjoiaHR0cHM6Ly9yYW1hbi5waWVjZXMuY2xvdWQifX0sInN0YXR1cyI6eyJjbG91ZCI6IlJVTk5JTkcifSwicHJvamVjdCI6InJ1bnRpbWUtdXNlci1jbG91ZC1ncm91cC0wIiwidXBkYXRlZCI6eyJ2YWx1ZSI6IjIwMjItMDUtMjVUMTc6MTM6MzAuNTc4NDgyWiIsInJlYWRhYmxlIjoiMTAgbW9udGhzIGFnbyJ9LCJ2ZXJzaW9uIjoiMy4xLjAifX19&user=e5c6879d-1526-4168-95a2-babbee7593d4)

Note: This flag is currently updated on iOS devices that are running iOS 13 and above.

## Tap Targets

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wn2htj22e3tsx9rxdyd1.gif "A gif of a mouse pressing a button and the button changing color to notify that the button was clicked.")

When you’re developing for mobile or any touch screen interfaces, you need to make sure that the tappable area for a button or any action is large enough that it can be tapped properly.

People with motor impairments may find it difficult to focus or concentrate their muscles on small areas and may find it challenging to tap the button if the tap target is too small. Even people with larger than average fingers may be frustrated by mis-tapping a small tap target.

The [Android Material Design guidelines](https://m2.material.io/design/layout/spacing-methods.html) for touch targets recommend a minimum of 48x48 [density-independent pixels (dp)](https://m2.material.io/design/layout/pixel-density.html#density-independence) for buttons, and [Apple recommends](https://developer.apple.com/design/human-interface-guidelines/components/menus-and-actions/buttons#best-practices) at least 44x44 dp. They also recommend adding spaces of at least 8 dp between interactive components to make them distinguishable from the surrounding components; also, make sure to avoid overlapping tap targets.

In Flutter UI, the minimum tap target size is set to 48 dp, in line with the Material Design guidelines. The same size is also used for iOS and all of the other platforms that Flutter supports.

## Semantics

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3jua6y51j394yjqc186h.gif "The word accessibility is being scanned and read by a screen reader.")

People with some forms of vision impairments may access your app with screen readers. Screen readers provide spoken feedback so that people can use their devices without looking at their screens.

Based on a user's gestures or through external controllers like a keyboard, screen readers narrate the semantics of the components, say whether something is tappable or not, and then dictate the results of those actions and other information that may help the user navigate through your app.

On Android, we have a screen reader called TalkBack. On iOS, we have VoiceOver; similar screen readers are available for other operating systems. People can enable them through the accessibility options on their devices.

By default, most Flutter widgets have some semantics. Flutter is smart enough to update those default semantics based on the data you pass to the required parameters of those widgets.

Let’s look at the following example where we navigate through a Flutter counter app with the help of Android's screen reader.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/38dlsfw9kq60h09fnb3o.png "A code snippet with several Flutter widgets. 
")
[Save to Pieces
](https://shared.code.pieces.app/?compressed=eyJiYXNlIjoiaHR0cHM6Ly9yYW1hbi5waWVjZXMuY2xvdWQiLCJzaGFyZSI6IjFiODlkYzMyLWU1MDItNGNhMy1iZGE2LWE3Y2RkM2ZmMTA4MSIsImFzc2V0IjoiNmI0Y2FmMjAtMmNjMi00YTUxLTk2ZWEtNmNlOThjNjNhZTc0IiwibmFtZSI6IlJhbWFuIEh1bmRhbCIsInRpdGxlIjoiRmx1dHRlciBTZW1hbnRpY3MiLCJkZXNjcmlwdGlvbiI6IkZsdXR0ZXIgc2VtYW50aWNzIGV4YW1wbGUgZnJvbSBQaWVjZXMgYmxvZyBhcnRpY2xlIiwidXNlciI6eyJzY2hlbWEiOnsibWlncmF0aW9uIjowLCJzZW1hbnRpYyI6Ik1BSk9SXzBfTUlOT1JfMF9QQVRDSF8xIn0sInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQVRYQUp3LWdjd2RmdXNQdm1SYnUxQTFBZm9OanBKT21UTU50b1Z6V1cwdj1zOTYtYyIsImVtYWlsIjoicmFtYW5AcGllY2VzLmFwcCIsImNyZWF0ZWQiOnsidmFsdWUiOiIyMDIyLTA0LTMwVDE4OjI3OjQzLjU1MVoiLCJyZWFkYWJsZSI6IjExIG1vbnRocyBhZ28ifSwidXBkYXRlZCI6eyJ2YWx1ZSI6IjIwMjItMDUtMjVUMTc6MDk6NTAuOTI5WiIsInJlYWRhYmxlIjoiMTAgbW9udGhzIGFnbyJ9LCJpZCI6ImU1YzY4NzlkLTE1MjYtNDE2OC05NWEyLWJhYmJlZTc1OTNkNCIsIm5hbWUiOiJSYW1hbiBIdW5kYWwiLCJhZXN0aGV0aWNzIjp7InRoZW1lIjp7ImRhcmsiOnRydWV9LCJmb250Ijp7InNpemUiOjE2fX0sImFsbG9jYXRpb24iOnsic2NoZW1hIjp7Im1pZ3JhdGlvbiI6MCwic2VtYW50aWMiOiJNQUpPUl8wX01JTk9SXzBfUEFUQ0hfMSJ9LCJpZCI6ImU1YzY4NzlkLTE1MjYtNDE2OC05NWEyLWJhYmJlZTc1OTNkNCIsInVzZXIiOiJlNWM2ODc5ZC0xNTI2LTQxNjgtOTVhMi1iYWJiZWU3NTkzZDQiLCJ1cmxzIjp7ImJhc2UiOnsic3RhdHVzIjoiUlVOTklORyIsInVybCI6Imh0dHBzOi8vdXNlci1lNWM2ODc5ZC0xNTI2LTQxNjgtOTVhMi1iYWJiZWU3NTkzZDQtZmhjbWJoZWtscS11Yy5hLnJ1bi5hcHAifSwiaWQiOnsic3RhdHVzIjoiUlVOTklORyIsInVybCI6Imh0dHBzOi8vZTVjNjg3OWQtMTUyNi00MTY4LTk1YTItYmFiYmVlNzU5M2Q0LnBpZWNlcy5jbG91ZCJ9LCJ2YW5pdHkiOnsic3RhdHVzIjoiUlVOTklORyIsInVybCI6Imh0dHBzOi8vcmFtYW4ucGllY2VzLmNsb3VkIn19LCJzdGF0dXMiOnsiY2xvdWQiOiJSVU5OSU5HIn0sInByb2plY3QiOiJydW50aW1lLXVzZXItY2xvdWQtZ3JvdXAtMCIsInVwZGF0ZWQiOnsidmFsdWUiOiIyMDIyLTA1LTI1VDE3OjEzOjMwLjU3ODQ4MloiLCJyZWFkYWJsZSI6IjEwIG1vbnRocyBhZ28ifSwidmVyc2lvbiI6IjMuMS4wIn19fQ==&user=e5c6879d-1526-4168-95a2-babbee7593d4)

When the app is first opened with the screen reader, it reads the title in the _AppBar_. As we tap different parts of the app, it gives feedback on the tapped component.

The default results are usually fine, but sometimes the default semantics won’t be able to provide a user with the proper information. In such cases, you can add your own semantics to suit your needs. Flutter provides us with several accessibility widgets that can help us to build more accessible apps.

One of those widgets is [Semantics](https://api.flutter.dev/flutter/widgets/Semantics-class.html). It allows you to add custom semantics to your Flutter widgets by providing you with various options to provide a description of a widget, its content, and whether it’s a button, slider, or other action component that a user can interact with. Also, you can describe the specific action that takes place if you double-tap, long press, or perform any other gestures on the component.

There’s a lot more to semantics than just the Semantics widget, including [MergeSemantics](https://api.flutter.dev/flutter/widgets/MergeSemantics-class.html) and [ExcludeSemantics](https://api.flutter.dev/flutter/widgets/ExcludeSemantics-class.html), which can be helpful in various scenarios. If you want to learn more about the best practices, ways you can use them, or dig a little deeper into the underlying workings of [Semantics in Flutter](https://www.didierboelens.com/2018/07/semantics/), which we haven’t covered here, check out some of the links to the learning materials I mention at the end of this article.

## On App Accessibility: A Note to Developers
Proper app accessibility should never be an optional task. The things some people take for granted can be difficult to achieve for others, and making sure that everyone can enjoy your apps and games is your responsibility as a developer.

Most of the time, we don’t even realize that there are people who are missing out on these experiences and totally neglect the users who would be enjoying your apps if you’d only learned how to make an app accessible.

Adding accessibility options takes more time and effort, but it’s something we can’t neglect. Many people depend on these digital solutions, and a developer's efforts can go a long way toward being truly helpful. You can always start small by improving things in your apps, gradually making them more accessible.

## Summary
We discussed some common app accessibility problems and how you can make your Flutter apps more accessible by considering accessibility solutions.

There’s far more to accessibility apps than what we discussed. I’ve shared some links below, which I think you should definitely take the time to explore. They go more in-depth on app accessibility in general and Flutter accessibility in particular. Building accessibility awareness can only make you a better developer and give your apps a wider audience with better UX.

Thanks for reading this article! If you found it helpful, please don’t forget to share it with other devs.

### More On Accessibility In Flutter
- [Apps for Everyone with Flutter — Lara Martin & Miguel Beltran | Flutter Europe](https://www.youtube.com/watch?v=Ywgt3cRKyrs&t=1805s)
- [Building in Accessibility with Flutter (Flutter Interact ‘19)](https://www.youtube.com/watch?v=bWbBgbmAdQs&t=138s)
- [Official Flutter documentation on Accessibility](https://docs.flutter.dev/development/accessibility-and-localization/accessibility)
- [A deep dive into Flutter’s accessibility widgets — Salih Guler
](https://medium.com/flutter-community/a-deep-dive-into-flutters-accessibility-widgets-eb0ef9455bc)

### Use Pieces to Store Your Flutter Snippets
When developing Flutter applications, you may have tons of widgets you save that you want to reuse later, but you just don't have them in a safe, easy-to-access place. Maybe you're combing through Flutter and Dart documentation, and you want to save examples that come in handy when implementing a new feature or figuring out which widget to use for app accessibility.

**Pieces** helps you save all of your useful code snippets efficiently through a desktop application and integrations. Using Pieces, you can save any code snippets from StackOverflow with the click of a button using the chrome extension, have your code autosaved from locally-hosted ML algorithms that recognize your code patterns, auto-classify snippets by language, share code with others using generated links, and more! The Pieces suite is continuously being developed, and there’s some groundbreaking stuff that is being put together to share, reuse, and save code snippets.

[Try Pieces now for free!](https://pieces.app/)