EAA Mobile App Accessibility 2026: Developer Checklist for iOS, Android & Progressive Web Apps
Post #4 in the sota.io EU Accessibility Compliance Series
If your mobile app is part of an in-scope service under the European Accessibility Act (EAA), Directive (EU) 2019/882, the enforcement clock started on June 28, 2025. Most developer guides focus on web applications and WCAG 2.1 AA. This one focuses on what is different for mobile: how EN 301 549 applies to native iOS, native Android, and Progressive Web Apps delivered to EU users.
The checklist at the end is structured so your iOS, Android, and web teams can work through it independently.
Does the EAA Cover Mobile Apps?
Short answer: yes, when the app is part of an in-scope service.
Under EAA Article 2, the services in scope include electronic communications services, banking and financial services offered to consumers, e-commerce services, services providing access to audiovisual media, and consumer-facing elements of transport services. Mobile apps delivering any of these services are covered by Article 13, which requires service providers to ensure those services meet the accessibility requirements in Article 4.
A fintech app with consumer accounts, an e-commerce shopping app, a video streaming app, a banking app — all are in scope. A pure B2B internal tooling app used only by employees is generally not in scope (employees are not "consumers" under the Directive's definition), but any consumer-facing component of your product is covered.
Microenterprise exemption (Article 22): If you have fewer than ten employees and annual turnover or balance sheet total below €2 million, the EAA does not apply to your service obligations. Note: this exemption applies per legal entity. If you are above either threshold, you must comply.
The Technical Standard: EN 301 549
The EAA delegates detailed technical requirements to the harmonized standard EN 301 549, "Accessibility requirements for ICT products and services." The 2018 version (v2.1.2) and the 2021 version (v3.2.1) are both referenced. EN 301 549 essentially embeds WCAG 2.1 AA for web content and adds additional clauses for software, hardware, and documentation.
For mobile apps, the relevant chapters are:
| Chapter | Scope |
|---|---|
| 5 | Generic requirements applicable to all ICT |
| 6 | ICT with two-way voice communication |
| 7 | ICT with video capabilities |
| 9 | Web content — WCAG 2.1 AA (applies to PWA and webviews) |
| 11 | Software — covers native mobile apps |
| 12 | Documentation and support services |
Chapter 11 is the key chapter for native mobile development.
Chapter 11: Software Requirements for Native Apps
EN 301 549 Chapter 11 translates accessibility principles into requirements for software that is not web content. For mobile developers, these are the most important clauses:
11.1–11.4: WCAG-aligned Criteria Applied to Software
Chapter 11 maps most WCAG 2.1 success criteria to software, adjusting the terminology where "web page" becomes "software" and "user agent" becomes "platform." For example:
- 11.1.1.1 Non-text content: Every non-decorative image, icon, or graphic in your app must have a text alternative accessible to screen readers.
- 11.1.4.3 Contrast minimum: Text and text in images must meet 4.5:1 contrast ratio (3:1 for large text ≥18pt regular or ≥14pt bold).
- 11.1.4.4 Resize text: Text must be resizable up to 200% without loss of content or functionality. On mobile this means supporting Dynamic Type (iOS) and font scale preferences (Android).
- 11.1.4.11 Non-text contrast: UI components and graphic elements that convey information must meet 3:1 contrast against adjacent colors.
- 11.2.1.1 Keyboard: On mobile, "keyboard" means any input method the platform supports — switch access, keyboard if attached, or sequential navigation. Your app must be operable through sequential navigation where a touch display is the primary input.
- 11.4.1.2 Name, role, value: Every user interface component must have an accessible name, role, and state that can be determined programmatically and set programmatically where the user can set it.
11.5: Interoperability with Assistive Technology
Clause 11.5 requires that software using platform accessibility services exposes information to those services correctly. For iOS this means conforming to the UIAccessibility protocol (or SwiftUI's equivalent) so VoiceOver can read your interface. For Android it means using AccessibilityNodeInfo correctly so TalkBack can navigate your app.
If your app uses a custom rendering engine or draws directly to a canvas (common in game engines, some data visualization libraries, cross-platform frameworks like Flutter), you must either use that engine's built-in accessibility bridge or implement one yourself.
11.6: Authoring Tools
If your app includes functionality that lets users create or edit content (a note editor, a form builder, a CMS app), those editing features must themselves be accessible, and the content your app generates must be accessible by default.
11.7: User Preferences
Clause 11.7 requires that software does not override user accessibility preferences unless the user explicitly requests it. This means:
- Do not hardcode font sizes. Respect the OS-level text size preference.
- Do not force animations for users who have set Reduce Motion.
- Do not disable the system's high-contrast mode.
iOS Accessibility Checklist
VoiceOver Support
VoiceOver reads your interface using the UIAccessibility API (UIKit) or the .accessibilityLabel, .accessibilityHint, and .accessibilityValue modifiers (SwiftUI).
Required for each interactive element:
- Every
UIButton,UIControl, and custom tappable view must have a descriptiveaccessibilityLabel. Not "button", not the icon name — a label that describes what it does ("Submit order", "Open navigation menu"). accessibilityHintis optional but useful for non-obvious actions.accessibilityValuefor dynamic state (e.g., a slider currently at "75%", a toggle that is "on").accessibilityTraitsmust reflect the element's role:.buttonfor buttons,.headerfor headings,.linkfor links,.selectedfor selected items.- Decorative images must be marked as
isAccessibilityElement = false(UIKit) or use.accessibilityHidden(true)(SwiftUI).
Custom containers:
If you use a UIView subclass as a logical container (e.g., a card that acts as a single tappable row), use UIAccessibilityContainer or accessibilityElements to expose the correct elements. Do not let VoiceOver visit every sub-element of a card if the card should act as one element.
Focus management:
When presenting a modal, sheet, or overlay, move VoiceOver focus to the first element in the new content: call UIAccessibility.post(notification: .screenChanged, argument: firstElement). When dismissing, return focus to a logical element in the originating view.
Dynamic Type
iOS users can increase font sizes system-wide via Settings → Accessibility → Display & Text Size → Larger Text. Your app must respond to these changes.
- Use
UIFont.preferredFont(forTextStyle:)(UIKit) or.font(.body)etc. (SwiftUI) instead of hardcoded point sizes. - Mark text views with
adjustsFontForContentSizeCategory = true. - Set
minimumScaleFactoronly if absolutely required for layout; do not use it to prevent the user's preferred size from being honored. - Test at "Accessibility Sizes" — enable in Simulator via Debug → Accessibility Settings → Accessibility Text Sizes.
Contrast and Color
- Run the Accessibility Inspector (Xcode → Window → Accessibility Inspector) and check the Audit tab for contrast violations.
- Do not rely solely on color to convey information (e.g., a red-only error state). Add a text label, icon, or pattern.
- Test with Color Filters → Grayscale enabled.
Tap Target Sizes
Apple's Human Interface Guidelines recommend a minimum tappable area of 44×44 points for interactive elements. EN 301 549 Clause 5.9 (referenced as a generic physical requirement) and WCAG 2.5.5 (AA in WCAG 2.2) both address target size. For EAA WCAG 2.1 AA compliance you are not required to meet 2.5.5, but 44×44pt is best practice that reduces errors.
If a visual element is smaller than 44×44pt, pad it with contentEdgeInsets (UIKit) or overlay a larger invisible tap area.
Platform Testing Tools
- Xcode Accessibility Inspector: Audit mode flags missing labels, contrast violations, and hit area problems.
- Simulator VoiceOver: Enable in Simulator → I/O → Hardware Keyboard → Toggle Software Keyboard, then Settings → Accessibility → VoiceOver. Navigate your entire app with swipe-right (next element) and double-tap (activate).
- Physical device VoiceOver: Siri → "Turn on VoiceOver" or Settings → Accessibility → VoiceOver. Testing on a real device catches issues the simulator misses.
Android Accessibility Checklist
TalkBack Support
TalkBack uses AccessibilityNodeInfo objects exposed by the Android accessibility framework. For most standard views (TextView, Button, EditText), the framework handles this automatically. For custom views you must override onInitializeAccessibilityNodeInfo.
Required for each interactive element:
- Set
android:contentDescriptiononImageView,ImageButton, and custom views. This is the accessible name TalkBack reads. - Set
android:contentDescription="@null"for purely decorative images. - For compound elements, consider making the parent the focusable element (
android:focusable="true") and setting itscontentDescriptionto a combined description of the children. - Use
android:importantForAccessibility="no"for views that should not receive TalkBack focus.
Roles:
Use ViewCompat.setAccessibilityDelegate() and AccessibilityNodeInfoCompat to set roles for custom components. Without explicit role information, TalkBack describes custom views as "unlabelled" or by class name.
Live regions:
When content updates dynamically (e.g., a form validation error appears, a loading indicator changes state), use ViewCompat.setAccessibilityLiveRegion() so TalkBack announces the change without requiring the user to navigate to it.
Font Scale
Android system-wide font scale is set in Settings → Display → Font size. Your app must scale text correctly.
- Use
spunits for all text (notdporpx). Thespunit respects the user's font scale setting. - Test at the maximum system font scale (currently 200% on Android 14+).
- Use
wrap_contentfor text containers and ensure layouts reflow rather than clipping or truncating.
Touch Target Sizes
Material Design guidelines recommend minimum touch targets of 48×48dp. You can implement this with minWidth="48dp" and minHeight="48dp" on clickable views, or by adding invisible padding.
For small visual elements (e.g., icons in a toolbar), wrap them in a ViewGroup with sufficient padding to ensure a 48×48dp tappable area.
Contrast
Android Studio's Layout Inspector does not natively audit contrast. Use the Accessibility Scanner app (by Google, available on Play Store) — it checks contrast, missing labels, and small touch targets across any app on the device. Also use the Color Contrast Analyzer desktop tool (by TPGi) to verify your specific color palette.
Platform Testing Tools
- Accessibility Scanner: Install on your test device and tap "Record" to get automated accessibility findings.
- TalkBack on device: Settings → Accessibility → TalkBack. Use two-finger swipe gestures for navigation. Navigate your complete user journey without looking at the screen.
- Android Studio Layout Inspector: Checks for
contentDescriptionpresence and some attribute issues. - Firebase Test Lab Robo Test: Includes accessibility checks in its crawl — surfaces missing labels and low contrast regions.
Progressive Web App (PWA) Checklist
PWAs are web content delivered over HTTPS. EN 301 549 Chapter 9 applies, which means WCAG 2.1 Level AA applies in full. The additional PWA-specific considerations are:
Offline and Service Worker UX
When your PWA is offline, the fallback UI must also be accessible. If you display an offline indicator, it must have a text label, not just a colored status dot.
Install Prompt and Manifest
The Web App Manifest name and short_name fields are used by the OS when the PWA is installed to a home screen. These should be descriptive and not truncated to meaninglessness.
Focus Management Across Routes
Single-page applications and PWAs often change content without a full page reload. After navigation, move focus to the page heading or the <main> element:
// After client-side navigation
document.querySelector('main').focus();
// or
document.querySelector('h1').focus();
This ensures screen reader users know a navigation occurred. Without explicit focus management, VoiceOver and TalkBack users hear nothing after a route change.
Touch-Specific Accessibility
WCAG 2.5.1 (Pointer Gestures, Level A) requires that functionality using multi-point gestures (pinch-to-zoom, two-finger swipe) can also be operated with a single pointer. If your PWA has gesture-based navigation, ensure every gesture has a button/tap equivalent.
WCAG 2.5.4 (Motion Actuation, Level A) means functionality triggered by device motion (shake to undo, tilt to scroll) must also be operable through a UI control.
ARIA and Role Correctness
- Use semantic HTML elements (
<button>,<nav>,<main>,<header>,<footer>,<article>) before reaching for ARIA. - When using ARIA, follow the rule: no ARIA is better than incorrect ARIA. A
<div role="button">that is not keyboard-focusable and does not respond to Enter/Space is worse than a<div>with no role. - Test with axe-core (browser extension or CI integration via
axe-playwright/@axe-core/react) — it catches the most common WCAG 2.1 AA violations automatically.
Keyboard Navigation
Every action in your PWA must be operable with a keyboard or a switch device. Specifically:
- No keyboard traps (WCAG 2.1.2): users must be able to navigate away from every component using Tab/Shift+Tab or arrow keys.
- Visible focus indicator (WCAG 2.4.7): do not use
outline: noneon focused elements without providing a replacement focus style. - Logical focus order (WCAG 1.3.2, 2.4.3): the Tab order must match the visual and logical reading order of the page.
Testing Your Mobile App for EAA
A three-layer testing strategy covers the full checklist efficiently:
Layer 1 — Automated (catches ~30–40% of issues)
| Platform | Tool | What it Catches |
|---|---|---|
| iOS | Xcode Accessibility Inspector (Audit) | Missing labels, contrast violations, small targets |
| Android | Accessibility Scanner app | Missing labels, contrast, small targets |
| PWA | axe-core (CI via Playwright) | WCAG 2.1 AA violations |
| All | Deque WorldSpace Attest (iOS/Android) | Custom accessibility rule sets |
Integrate automated checks into CI so violations block PRs rather than accumulating.
Layer 2 — Manual with Assistive Technology (catches 40–50% not found by automation)
- iOS: Run VoiceOver and navigate your complete user journey. Every action must be discoverable and operable by VoiceOver alone.
- Android: Run TalkBack and do the same.
- PWA: Run with Windows Narrator + Chrome, NVDA + Firefox, VoiceOver on macOS + Safari. Test keyboard-only navigation.
Target at least four user journeys per platform: onboarding/signup, core workflow task, error recovery, settings/account.
Layer 3 — User testing with disabled users (qualitative, catches what technology misses)
Automated tools and developer testing find technical violations. They do not catch confusion, cognitive load problems, or workarounds that technically pass but are unusable. At least once before launch, test with actual users who rely on screen readers or switch access.
Enforcement Timeline and Non-Compliance Consequences
June 28, 2025: Services placed on the market after this date must comply immediately. If you launch a new mobile app or a significant new version of an existing app after this date, EAA requirements apply.
June 28, 2030: Existing services (those already being provided before June 28, 2025) have a five-year transition period. However, "existing service" does not mean you can freeze your app — you must still ensure that material updates to the service comply.
Enforcement mechanism (Article 26): Each EU member state designates market surveillance authorities. These authorities can request compliance documentation, conduct audits, and issue corrective orders. Article 24 establishes that penalties must be "effective, proportionate, and dissuasive" and must take into account the scale of the infringement, the number of users affected, and whether the infringement was intentional.
Accessibility statement: Service providers are required to document their accessibility status. For mobile apps, this means publishing an accessibility conformance report (typically following VPAT format or the EN 301 549 conformance template) and making it available in your app store listing and in-app settings.
Your Developer Checklist
iOS Checklist
- Every interactive element has a meaningful
accessibilityLabel - Decorative images are hidden from assistive technology (
isAccessibilityElement = false) - Custom containers correctly group or expose child elements
- Modal/sheet presentation moves VoiceOver focus to new content
- Text uses Dynamic Type styles (not hardcoded point sizes)
-
adjustsFontForContentSizeCategory = trueon all text views - Contrast ratio ≥ 4.5:1 for body text, ≥ 3:1 for large text
- Color is not the only means of conveying information
- Tap targets are ≥ 44×44 points
- App passes Xcode Accessibility Inspector audit with zero errors
- Full VoiceOver navigation test completed by a developer on physical device
- Animations respect Reduce Motion preference
Android Checklist
- Every
ImageViewandImageButtonhas acontentDescription - Decorative images have
importantForAccessibility="no" - Custom views expose correct roles via
AccessibilityNodeInfoCompat - Dynamic content changes use
setAccessibilityLiveRegion() - All text uses
spunits - App passes at maximum font scale (200%) without clipping
- Touch targets are ≥ 48×48dp
- Contrast verified with Accessibility Scanner
- Full TalkBack navigation test completed on physical device
- Compatibility verified with Android Switch Access
PWA / Web Checklist
- axe-core passes with zero critical/serious violations in CI
- Semantic HTML used for all structural elements
- All interactive elements are keyboard operable
- No keyboard traps
- Focus indicator is visible on all interactive elements
- Focus management implemented after client-side navigation
- ARIA attributes are correct where used
- Images have alt text; decorative images have
alt="" - Color is not the only means of conveying information
- Contrast ratio ≥ 4.5:1 for body text
- Touch targets ≥ 44×44 CSS pixels
- Tested with VoiceOver + Safari (macOS), NVDA + Firefox (Windows)
Cross-Platform
- Accessibility statement prepared and published
- App store listing includes accessibility information
- Automated accessibility tests run in CI
- Issue tracking includes "accessibility" label for regression tracking
- Microenterprise exemption evaluated and documented if applicable
Deploying on EU Infrastructure
Accessibility compliance is a legal obligation — but it is also a quality signal. Apps that work correctly with VoiceOver and TalkBack tend to also work correctly in unexpected hardware configurations, with poor network conditions, and across locales.
If your mobile backend runs on EU-compliant infrastructure (GDPR, no CLOUD Act exposure), you can address both the EAA accessibility requirements and the data sovereignty requirements from a single deployment architecture. The same API serving your iOS and Android clients can run on Hetzner Germany, within a managed PaaS that handles the infrastructure compliance layer.
For teams evaluating EU-hosted options for their mobile backend, sota.io offers managed deployments on Hetzner Germany with git-based deploys for any language.
Summary
The EAA makes mobile app accessibility a legal requirement for in-scope services. The technical standard is EN 301 549, which applies WCAG 2.1 AA to web content and adds Chapter 11 requirements for native software. The practical checklist is: VoiceOver-compliant iOS, TalkBack-compliant Android, WCAG 2.1 AA-compliant PWA, automated testing in CI, and at least one VoiceOver/TalkBack full-journey test before each release.
The June 28, 2025 deadline has passed for new services. The June 28, 2030 deadline for existing services sounds distant — but accessibility remediation on a large app typically takes 6–18 months. If you start now, you will meet 2030 comfortably. If you wait until 2029, you will not.
EU-Native Hosting
Ready to move to EU-sovereign infrastructure?
sota.io is a German-hosted PaaS — no CLOUD Act exposure, no US jurisdiction, full GDPR compliance by design. Deploy your first app in minutes.