Flutter Improving Accessibility
Published by qunnnn in agents
What this skill does
Configures a Flutter app to support assistive technologies like Screen Readers. Use when ensuring an application is usable for people with disabilities.
Add Flutter Improving Accessibility to your agent
Review the source and files first. When you are ready, copy the prompt instruction or use the CLI command supported by your environment.
Install with a prompt
Paste this into a compatible coding agent:
add this skill "flutter-improving-accessibility" from https://github.com/qunnnn/agentsInstall with the CLI
Run this command in a controlled environment after reviewing the repository:
npx skills add https://github.com/qunnnn/agents --skill flutter-improving-accessibilitySkill instructions
Flutter Accessibility
Contents
- UI Design Standards
- Accessibility Widgets
- Web Accessibility
- Workflow: Accessibility Implementation
- Workflow: Accessibility Validation
- Examples
UI Design Standards
Design layouts to accommodate dynamic scaling and high visibility. Flutter automatically calculates font sizes based on OS-level accessibility settings.
Minimum Requirements
| Requirement | Standard |
|---|---|
| Color Contrast (small text) | ≥ 4.5:1 ratio (W3C WCAG AA) |
| Color Contrast (large text) | ≥ 3.0:1 ratio (18pt+ regular or 14pt+ bold) |
| Tap Target Size | ≥ 48 × 48 logical pixels |
| Font Scaling | Layouts must not clip/overflow at maximum OS font settings |
Design Rules
- Font Scaling: Ensure layouts provide sufficient room when font sizes are increased to maximum OS settings. Avoid hardcoding fixed heights on text containers.
- Color Contrast: Never rely solely on color to convey information. Always pair with icons, labels, or patterns.
- Tap Targets: Use
MaterialorInkWellwidgets with minimum 48×48 touch areas. Add padding to small interactive elements.
Accessibility Widgets
Use Flutter's catalog of accessibility widgets to manipulate the semantics tree exposed to assistive technologies (TalkBack, VoiceOver).
| Widget | Purpose |
|---|---|
Semantics | Annotate the widget tree with meaning. Assign roles using SemanticsRole enum. |
MergeSemantics | Merge descendants into a single selectable node for screen readers. |
ExcludeSemantics | Hide decorative/redundant sub-widgets from accessibility tools. |
When to Use Each Widget
Semantics: Custom interactive components (buttons, list items, toggles) that don't automatically expose their role.MergeSemantics: Composite widgets where individual children shouldn't be separate screen reader stops (e.g., a card with icon + text + subtitle).ExcludeSemantics: Purely decorative elements (background images, decorative dividers, redundant icons next to labels).
Web Accessibility
Flutter web renders UI on a single canvas, requiring a specialized DOM layer.
- Semantics Disabled by Default: For performance, web accessibility is off by default. Users can enable via an invisible button.
- Programmatic Enablement: For web-first apps requiring default accessibility, force semantics at startup:
import 'package:flutter/foundation.dart';
import 'package:flutter/semantics.dart';
void main() {
if (kIsWeb) {
SemanticsBinding.instance.ensureSemantics();
}
runApp(const MyApp());
}
- Semantic Roles: Standard widgets (
TabBar,MenuAnchor,Table) automatically map to ARIA roles. For custom components, explicitly assignSemanticsRolevalues.
Workflow: Accessibility Implementation
Apply this checklist during UI development:
- Verify all interactive elements have a minimum tap target of 48×48 pixels.
- Test layout with maximum OS font size settings — ensure no text clipping or overflow.
- Validate color contrast ratios (4.5:1 for normal text, 3.0:1 for large text).
- Wrap custom interactive widgets in
Semanticsand assign the appropriateSemanticsRole. - Group complex composite widgets using
MergeSemanticsto prevent screen reader fatigue. - Hide decorative elements from screen readers using
ExcludeSemantics. - If targeting web, verify ARIA roles are correctly mapped.
- Add
Tooltipto icon-only buttons for screen reader context.
Workflow: Accessibility Validation
Run this loop when finalizing a view or component:
- Run validator: Execute accessibility tests or use OS-level screen readers (VoiceOver on iOS/macOS, TalkBack on Android).
- Review errors: Identify unannounced interactive elements, trapped focus, or clipped text.
- Fix: Apply
Semantics, adjust constraints, or modify colors. - Repeat until the screen reader provides a clear, logical traversal of the UI.
Automated Testing
testWidgets('button has correct semantics', (tester) async {
await tester.pumpWidget(const MaterialApp(home: MyButton()));
final semantics = tester.getSemantics(find.byType(MyButton));
expect(semantics.label, 'Submit form');
expect(semantics.hasAction(SemanticsAction.tap), isTrue);
});
Examples
Custom Component with Semantics
class CustomListItem extends StatelessWidget {
final String title;
final String subtitle;
final VoidCallback onTap;
const CustomListItem({
super.key,
required this.title,
required this.subtitle,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return MergeSemantics(
child: Semantics(
button: true,
label: '$title, $subtitle',
child: InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.all(16.0), // Ensures > 48px tap target
child: Row(
children: [
ExcludeSemantics(
child: Icon(Icons.person), // Decorative — already described in label
),
const SizedBox(width: 16),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: const TextStyle(fontSize: 16)),
Text(subtitle, style: const TextStyle(fontSize: 14)),
],
),
],
),
),
),
),
);
}
}
Icon Button with Tooltip
// Always add tooltip to icon-only buttons for screen reader users
IconButton(
icon: const Icon(Icons.delete),
tooltip: 'Delete item',
onPressed: () => _deleteItem(),
)
Image with Semantic Description
Semantics(
label: 'Profile photo of the service provider',
child: ExcludeSemantics(
child: CircleAvatar(
backgroundImage: NetworkImage(user.avatarUrl),
radius: 24,
),
),
)
Anti-patterns
- ❌ Using color alone to indicate status (error states, success, warnings)
- ❌ Icon-only buttons without
tooltiporSemanticslabel - ❌ Interactive elements smaller than 48×48 logical pixels
- ❌ Hardcoding text container heights (breaks with font scaling)
- ❌ Leaving decorative images announced by screen readers
- ❌ Not testing with actual screen readers (VoiceOver / TalkBack)
Resources
- https://docs.flutter.dev/ui/accessibility-and-internationalization/accessibility
- https://docs.flutter.dev/ui/adaptive-responsive
- https://www.w3.org/WAI/WCAG21/quickref/
- https://api.flutter.dev/flutter/widgets/Semantics-class.html
- https://api.flutter.dev/flutter/widgets/MergeSemantics-class.html
- https://api.flutter.dev/flutter/widgets/ExcludeSemantics-class.html
Files included
- SKILL.md

