111 lines
5.5 KiB
Markdown
111 lines
5.5 KiB
Markdown
---
|
|
name: "flutter-improving-accessibility"
|
|
description: "Configures a Flutter app to support assistive technologies like Screen Readers. Use when ensuring an application is usable for people with disabilities."
|
|
metadata:
|
|
model: "models/gemini-3.1-pro-preview"
|
|
last_modified: "Thu, 12 Mar 2026 22:17:37 GMT"
|
|
|
|
---
|
|
# Implementing Flutter Accessibility
|
|
|
|
## Contents
|
|
- [UI Design and Styling](#ui-design-and-styling)
|
|
- [Accessibility Widgets](#accessibility-widgets)
|
|
- [Web Accessibility](#web-accessibility)
|
|
- [Adaptive and Responsive Design](#adaptive-and-responsive-design)
|
|
- [Workflows](#workflows)
|
|
- [Examples](#examples)
|
|
|
|
## UI Design and Styling
|
|
Design layouts to accommodate dynamic scaling and high visibility. Flutter automatically calculates font sizes based on OS-level accessibility settings.
|
|
|
|
* **Font Scaling:** Ensure layouts provide sufficient room to render all contents when font sizes are increased to their maximum OS settings. Avoid hardcoding fixed heights on text containers.
|
|
* **Color Contrast:** Maintain a contrast ratio of at least 4.5:1 for small text and 3.0:1 for large text (18pt+ regular or 14pt+ bold) to meet W3C standards.
|
|
* **Tap Targets:** Enforce a minimum tap target size of 48x48 logical pixels to accommodate users with limited dexterity.
|
|
|
|
## Accessibility Widgets
|
|
Utilize Flutter's catalog of accessibility widgets to manipulate the semantics tree exposed to assistive technologies (like TalkBack or VoiceOver).
|
|
|
|
* **`Semantics`**: Use this to annotate the widget tree with a description of the meaning of the widgets. Assign specific roles using the `SemanticsRole` enum (e.g., button, link, heading) when building custom components.
|
|
* **`MergeSemantics`**: Wrap composite widgets to merge the semantics of all descendants into a single selectable node for screen readers.
|
|
* **`ExcludeSemantics`**: Use this to drop the semantics of all descendants, hiding redundant or purely decorative sub-widgets from accessibility tools.
|
|
|
|
## Web Accessibility
|
|
Flutter web renders UI on a single canvas, requiring a specialized DOM layer to expose structure to browsers.
|
|
|
|
* **Enable Semantics:** Web accessibility is disabled by default for performance. Users can enable it via an invisible button (`aria-label="Enable accessibility"`).
|
|
* **Programmatic Enablement:** If building a web-first application requiring default accessibility, force the semantics tree generation at startup.
|
|
* **Semantic Roles:** Rely on standard widgets (`TabBar`, `MenuAnchor`, `Table`) for automatic ARIA role mapping. For custom components, explicitly assign `SemanticsRole` values to ensure screen readers interpret the elements correctly.
|
|
|
|
## Adaptive and Responsive Design
|
|
Differentiate between adaptive and responsive paradigms to build universal applications.
|
|
|
|
* **Responsive Design:** Adjust the placement, sizing, and reflowing of design elements to fit the available screen space.
|
|
* **Adaptive Design:** Select appropriate layouts (e.g., bottom navigation vs. side panel) and input mechanisms (e.g., touch vs. mouse/keyboard) to make the UI usable within the current device context. Design to the strengths of each form factor.
|
|
|
|
## Workflows
|
|
|
|
### Task Progress: Accessibility Implementation
|
|
Copy this checklist to track accessibility compliance during UI development:
|
|
|
|
- [ ] Verify all interactive elements have a minimum tap target of 48x48 pixels.
|
|
- [ ] Test layout with maximum OS font size settings to ensure no text clipping or overflow occurs.
|
|
- [ ] Validate color contrast ratios (4.5:1 for normal text, 3.0:1 for large text).
|
|
- [ ] Wrap custom interactive widgets in `Semantics` and assign the appropriate `SemanticsRole`.
|
|
- [ ] Group complex composite widgets using `MergeSemantics` to prevent screen reader fatigue.
|
|
- [ ] Hide decorative elements from screen readers using `ExcludeSemantics`.
|
|
- [ ] If targeting web, verify ARIA roles are correctly mapped and consider programmatic enablement of the semantics tree.
|
|
|
|
### Feedback Loop: Accessibility Validation
|
|
Run this loop when finalizing a view or component:
|
|
1. **Run validator:** Execute accessibility tests or use OS-level screen readers (VoiceOver/TalkBack) to navigate the view.
|
|
2. **Review errors:** Identify unannounced interactive elements, trapped focus, or clipped text.
|
|
3. **Fix:** Apply `Semantics`, adjust constraints, or modify colors. Repeat until the screen reader provides a clear, logical traversal of the UI.
|
|
|
|
## Examples
|
|
|
|
### Programmatic Web Accessibility Enablement
|
|
If targeting web and requiring accessibility by default, initialize the semantics binding before running the app.
|
|
|
|
```dart
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/semantics.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
void main() {
|
|
if (kIsWeb) {
|
|
SemanticsBinding.instance.ensureSemantics();
|
|
}
|
|
runApp(const MyApp());
|
|
}
|
|
```
|
|
|
|
### Custom Component Semantics
|
|
If building a custom widget that acts as a list item, explicitly define its semantic role so assistive technologies and web ARIA mappings interpret it correctly.
|
|
|
|
```dart
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/semantics.dart';
|
|
|
|
class CustomListItem extends StatelessWidget {
|
|
final String text;
|
|
|
|
const CustomListItem({super.key, required this.text});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Semantics(
|
|
role: SemanticsRole.listItem,
|
|
label: text,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(12.0), // Ensures > 48px tap target if interactive
|
|
child: Text(
|
|
text,
|
|
style: const TextStyle(fontSize: 16), // Ensure contrast ratio > 4.5:1
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
```
|