Dev.to · 11 min read

Accessible by Platform: How iOS and Android Differ from the Web

Accessible by Platform: How iOS and Android Differ from the Web

The guidelines you know were written for web pages. Native apps borrow their intent and rewrite the mechanics. If your accessibility strategy assumes one rulebook covers all three platforms, you are shipping compliance debt you cannot see. There is a comfortable myth in a lot of accessibility programs: that WCAG is WCAG, a checklist is a checklist, and once your team has learned to write accessible HTML they have learned to build accessible products. The web team passes an audit, the mobile team is told to "follow the same standard," and everyone assumes the work transfers. It mostly does not. The principles transfer beautifully — perceivable, operable, understandable, robust are universal. But the moment you leave the browser, almost every mechanism used to satisfy those principles changes. The markup changes. The assistive technology changes. The gestures change. The way a screen reader builds its picture of your interface changes. A button that is perfectly accessible on the web can be completely invisible to VoiceOver, and a label that TalkBack announces cleanly can be meaningless noise in Safari. This piece is a map of where web, iOS, and Android genuinely diverge, and why "build it once, make it accessible once" is one of the more expensive assumptions a product organization can make. One standard, three interpretations Start with the standard itself, because even here the ground is less solid than most teams assume. WCAG was developed for web content, so some of its terminology and conformance concepts — a "web page" as the unit of conformance, for instance — assume a web context. The success criteria themselves are intentionally written to be largely technology-neutral, but native applications have no HTML DOM, which means those web-shaped requirements often need platform-specific interpretation and implementation. To bridge the gap, the W3C publishes interpretive guidance rather than separate app standards. WCAG2ICT provides W3C guidance on applying WCAG 2.0, 2.1, and 2.2 to non-web documents and software. Building on top of it, the Mobile Accessibility Task Force published WCAG2Mobile — "Guidance on Applying WCAG 2.2 to Mobile Applications" — as a Draft Note in May 2025. Both are worth reading with the word guidance firmly in mind: they are informative, not normative. WCAG2Mobile in particular remains a work in progress — W3C states that it does not establish requirements, is not endorsed by W3C or its members, and may change. What it does is translate existing criteria: it reframes the unit of conformance from "a web page" to a single screen or view within the application, and works through which criteria mean something different, or nothing at all, on a touchscreen. Layer regulation on top and the picture gets more textured — and, importantly, less uniform than a single "your app must be accessible" would suggest. In Europe, the European Accessibility Act has applied to covered products and services since 28 June 2025. EN 301 549 provides an important European technical framework for ICT accessibility, covering web and non-web software, and it is being revised under the EU standardization process to support the EAA as well as the Web Accessibility Directive. In the United States, the framework varies by context rather than resolving into one rule. Section 508 incorporates WCAG requirements for federal ICT, including provisions adapted for non-web software. Under the ADA, Title II now points somewhere specific: the Department of Justice has adopted WCAG 2.1 Level AA as the technical standard for state and local government web content and mobile applications. Private-sector obligations under ADA Title III are less prescriptive — accessibility obligations exist, but federal regulations do not currently establish WCAG as a universal technical standard for all private mobile applications. The common thread across all of this is intent; the technical means of satisfying it splinters across three toolchains. The accessibility tree is built from different materials Every platform exposes an accessibility tree — a parallel representation of the interface that assistive technology actually reads, distinct from the visual layout. This is the single most important concept for understanding why platforms differ, because the tree is assembled from completely different source materials on each one. On the web, the tree is derived from semantic HTML, supplemented and corrected by ARIA. A carries an implicit role; a becomes a landmark; aria-label, aria-expanded, and aria-live patch in the meaning that markup alone cannot express. The browser mediates everything, and it is forgiving — sometimes too forgiving, which is why so much broken markup still limps along. On iOS, there is no DOM and no ARIA. Accessibility is expressed through the UIAccessibility API in UIKit, or through accessibility modifiers in SwiftUI. Instead of ARIA roles you have accessibility traits — a control is marked .button, .header, .adjustable, .selected, and so on. Instead of aria-label you set an accessibilityLabel, an accessibilityHint, and an accessibilityValue. The concepts rhyme with ARIA, but the vocabulary, the defaults, and the failure modes are entirely their own. On Android, the tree is populated by AccessibilityNodeInfo, drawn from the View hierarchy or from Jetpack Compose semantics. You supply a contentDescription, mark elements as headings, define state descriptions, and manage focusable and important-for-accessibility flags. Compose changed the model again by making semantics a first-class, declarative property rather than something bolted onto a View. The practical consequence: an accessible name that is correct on all three platforms had to be authored three separate times, in three different APIs, by developers who each need genuine platform expertise. There is no shared attribute that flows from one to the others. Concept Web iOS Android Accessible name Text content, aria-label, alt accessibilityLabel contentDescription Role / type HTML element or ARIA role Accessibility trait (e.g. .button) Class name / semantics role State aria-expanded, aria-checked Traits + accessibilityValue State description, checked/selected flags Live updates aria-live region UIAccessibility.post(notification:) announceForAccessibility / live region Primary screen reader JAWS, NVDA, VoiceOver (desktop) VoiceOver TalkBack Primary test tool axe, Lighthouse, WAVE Xcode Accessibility Inspector Accessibility Scanner, Espresso checks The interaction model is not the same interaction model Even when the tree is correct, users reach it differently, and this is where a lot of "technically labeled but practically unusable" interfaces are born. The web inherited a keyboard-first focus model. Tab order, focus rings, tabindex, and managing focus after dynamic changes are the backbone of web accessibility. Screen reader users on a desktop navigate through a rich set of shortcuts — by heading, by landmark, by form field — layered over that keyboard model. Mobile screen readers replace nearly all of that with gesture navigation over a flat linear order. A VoiceOver user swipes right to move to the next element and uses the rotor — a twisting gesture — to switch between navigating by headings, links, form controls, or characters. A TalkBack user swipes similarly and uses reading controls and the local context menu to change granularity. There is no visible focus ring to reason about, no Tab key in the everyday flow, and the "reading order" is whatever order your elements sit in the accessibility tree — which may have nothing to do with their visual position. This has a direct design cost. WCAG 2.2 added Success Criterion 2.5.7, Dragging Movements, precisely because touch-based interactions like swipe-to-delete or drag-to-reorder can be impossible for someone who cannot perform a precise drag. On the web you might solve that with keyboard operability. On iOS and Android you solve it with an alternative such as an edit mode, a long-press menu, or explicit buttons — a different remedy for the same requirement. Touch targets: three numbers for one idea Sizing is the cleanest illustration of divergence, because everyone agrees on the principle and no one agrees on the number. Apple's Human Interface Guidelines call for a minimum tappable area of 44 × 44 points. Android's Material guidance calls for a minimum touch target of 48 × 48 density-independent pixels. WCAG 2.2 introduced Success Criterion 2.5.8, Target Size (Minimum), at 24 × 24 CSS pixels for AA — a deliberately lower floor with several exceptions, meant as a baseline rather than best practice. It helps to be precise about what these numbers are: Apple's 44 pt and Android's 48 dp are platform design and accessibility guidance, while WCAG's 24 CSS px is a conformance criterion with its own specified exceptions. A design system that treats a single number as a universal accessibility threshold therefore risks missing platform-specific guidance or an applicable conformance requirement. Points, density-independent pixels, and CSS pixels are different units, and each framework applies them in a different context. This is exactly the kind of detail that survives a checklist audit and fails a real user with a tremor or large fingertips. System settings do the heavy lifting — differently A great deal of mobile accessibility is not something you build so much as something you must not break. Both platforms ship powerful user-level settings, and your job is to respect them. Text scaling is the classic example. iOS has Dynamic Type; Android has a font-size (and, more recently, bold-text and display-size) preference. A user may set text to well over 200% of its default. On the web, the analog is browser zoom and reflow, governed by WCAG's Reflow and Resize Text criteria. Build a fixed-height card with fixed-point text and it looks identical in every screenshot — and clips the moment a real user enlarges their font. Testing at default size proves nothing here. The same pattern repeats for reduced motion (respected via prefers-reduced-motion on the web, and via system flags your native code must query), dark mode and contrast settings, and orientation. Each platform surfaces these preferences through its own API, and honoring them is a per-platform engineering task, not a shared one. The cross-platform trap By now the obvious hope is a framework that papers over all of this — React Native, Flutter, or a shared web view — so accessibility can be written once and mapped everywhere. These frameworks do provide accessibility props, and they are far better than they used to be. But they are abstraction layers, and abstraction layers leak. A React Native accessibilityRole has to be translated into an iOS trait and an Android node role, and the mapping is not always faithful. A Flutter Semantics widget must render correctly through two very different platform channels. Custom components — the interesting, differentiated parts of any product — are exactly where these mappings are thinnest and where announcements go wrong. The framework gives you a single place to declare intent; it does not guarantee that VoiceOver and TalkBack both interpret that intent the same way. You still have to test on both, with the real screen readers, on real devices. Cross-platform code lets you write the accessibility once. It does not let you verify it once. Those are different promises, and confusing them is how "accessible" apps ship that no screen reader user can actually operate. What this means for how you run the program The recurring theme in all of this — and, if you have read my other work, a theme I return to often — is the gap between passing a check and a human being able to use the thing. Automated tooling and cross-platform abstractions are both wonderful at producing the first while quietly failing at the second. They generate what I have elsewhere called plausible accessibility: markup and labels that look right, satisfy a scanner, and collapse under a real user's assistive technology. A few practical commitments follow from taking platform divergence seriously: Budget three test surfaces, not one. A web audit, a VoiceOver pass on iOS, and a TalkBack pass on Android are three distinct activities. Staffing and scheduling should reflect that. Hire or train platform-native accessibility skill. "Our developers know ARIA" does not mean they know UIAccessibility traits or Compose semantics. These are separate competencies. Test with the actual assistive technology, on real devices. Simulators and automated node checks miss the announcement order, the rotor experience, and the reading flow that define whether the app is usable. Map your design system to each platform's numbers. One token for touch-target size, resolved to 44 pt, 48 dp, and a conformant web value — not a single hard-coded figure. Treat framework accessibility as a starting point, not a guarantee. Verify the leaked abstractions, especially on custom components. WCAG gave us a shared language for what accessibility means. It did not give us a shared implementation, and the arrival of WCAG2ICT and WCAG2Mobile is the standards world formally acknowledging as much. The organizations that build genuinely accessible products are the ones that stop treating "web, iOS, and Android" as one deliverable with three skins, and start treating them as three craft disciplines aimed at the same human outcome. The intent is universal. The work is not. Plan for the work.

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More Programming & Dev News