capacitor-accessibility
Skill75 starsChanged 32 days agoMITView on GitHub
Makes Capacitor apps work with VoiceOver, TalkBack, Dynamic Type / Android font scale, Switch Control, hardware keyboards, Reduce Motion and Increase Contrast. Covers Capacitor-specific gaps - WKWebView not following iOS Dynamic Type, Android WebView text zoom breaking layouts, zoomEnabled/user-scalable, SPA route changes not announced, native views under the WebView (maps, camera preview) being unreachable, @capacitor/screen-reader (isEnabled, speak, stateChange) and @capacitor/text-zoom (getPreferred, set) - plus testing with Accessibility Inspector, simctl content_size, adb font_scale, TalkBack and axe-core, mapped to WCAG 2.2. Do not use for Ionic component styling (use ionic-design), notch/home-indicator layout (use safe-area-handling), keyboard overlap bugs (use capacitor-keyboard), automated test framework setup (use capacitor-testing), or App Store metadata (use capacitor-app-store).
1 other project uses a version of this.
Adopted by
Most recently taken up by
- Aver005/agent-skillstheir own version, first seen Feb 14, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- Aver005/agent-skills★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository56 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- capacitor-app-intentsSkill
- capacitor-apple-review-preflightSkill
- capacitor-app-storeSkill
- capacitor-app-upgradesSkill
- capacitor-app-upgrade-v4-to-v5Skill
- capacitor-app-upgrade-v5-to-v6Skill
- capacitor-app-upgrade-v6-to-v7Skill
- capacitor-app-upgrade-v7-to-v8Skill
- capacitor-app-upgrade-v8-to-v9Skill
- capacitor-best-practicesSkill
- capacitor-ci-cdSkill
- capacitor-deep-linkingSkill
- capacitor-ios-resizabilitySkill
- capacitor-ios-security-hardeningSkill
- capacitor-keyboardSkill
- capacitor-mcpSkill
- capacitor-offline-firstSkill
- capacitor-performanceSkill
- capacitor-plugin-spm-supportSkill
- capacitor-pluginsSkill
- capacitor-plugin-upgradesSkill
- capacitor-plugin-upgrade-v4-to-v5Skill
- capacitor-plugin-upgrade-v5-to-v6Skill
- capacitor-plugin-upgrade-v6-to-v7Skill
- capacitor-plugin-upgrade-v7-to-v8Skill
- capacitor-plugin-upgrade-v8-to-v9Skill
- capacitor-push-notificationsSkill
- capacitor-securitySkill
- capacitor-splash-screenSkill
- capacitor-testingSkill
- capacitor-uiscene-migrationSkill
- capawesome-live-update-migrationSkill
- capgo-cli-usageSkill
- capgo-cloudSkill
- capgo-live-updatesSkill
- capgo-native-buildsSkill
- capgo-organization-managementSkill
- capgo-release-managementSkill
- capgo-release-workflowsSkill
- cocoapods-to-spmSkill
- cordova-to-capacitorSkill
- debugging-capacitorSkill
- framework-to-capacitorSkill
- ionic-appflow-migrationSkill
- ionic-designSkill
- ionic-enterprise-sdk-migrationSkill
- ios-android-logsSkill
- konsta-uiSkill
- safe-area-handlingSkill
- skill-creatorSkill
- sqlite-to-fast-sqlSkill
- subscription-app-revenueSkill
- tailwind-capacitorSkill
- webapp-to-capacitorSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 47
Focus after native round-trips: After a native modal (camera, share, auth browser) closes, focus may land on <body>.
- Distinctive: line 70
Only load when the topic is in play:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Accessibility in Capacitor Apps
The UI is web content inside WKWebView / Android WebView, so standard semantic HTML and ARIA do most of the work. This skill covers where the WebView and native layers behave differently from a browser.
When to Use
TRIGGER when:
- User asks for VoiceOver/TalkBack support, an accessibility audit, WCAG 2.2 / EAA / ADA compliance.
- Text does not grow with iOS Larger Text, or the layout breaks at large Android font sizes.
- Screen reader does not announce page changes, toasts, or loading states.
- A native view (map, camera preview, video player) cannot be reached by the screen reader.
- User wants
@capacitor/screen-readeror@capacitor/text-zoom.
Do not use:
- Ionic component APIs/theming ->
ionic-design; Konsta/Tailwind ->konsta-ui,tailwind-capacitor. - Content under notch/home indicator ->
safe-area-handling. - Keyboard covering inputs ->
capacitor-keyboard. - E2E test infrastructure ->
capacitor-testing.
Procedure
- Inventory screens into a TODO list (auth, main tabs, forms, modals, media, settings). Audit one at a time.
- Automated pass on the web build: run axe (
@axe-core/playwrightin tests, ornpx @axe-core/cli@latest http://localhost:5173) and fix violations first (names, roles, contrast, labels). - Device pass per screen with VoiceOver and TalkBack, largest text size, Reduce Motion, and a Bluetooth keyboard (iPad). Use the checks in
references/testing.md. - Fix Capacitor-specific traps below.
- Report findings per screen with WCAG criterion, severity, and fix before large refactors; ask before changing design tokens (colors, font sizes).
Capacitor-Specific Traps
- iOS Dynamic Type is ignored by default. WKWebView renders
px/remtext at fixed size regardless of Settings > Accessibility > Larger Text. Options:- CSS:
html { font: -apple-system-body; }and size everything else inrem/em(WebKit maps this to the user's content size category; updates live). - Or
TextZoom.getPreferred()thenTextZoom.set({ value })from@capacitor/text-zoomon launch and onresume. On iPad this requiresios.preferredContentMode: 'mobile'incapacitor.config.*. Pick one, not both, or text scales twice.
- CSS:
- Android font scale applies automatically. Android WebView scales text with the system font size, so fixed-height containers,
line-clamp, and absolute layouts overflow at 200%. Test withadb shell settings put system font_scale 2.0and design for reflow (WCAG 1.4.4, 1.4.10). - Pinch zoom.
zoomEnableddefaults tofalseand many templates shipuser-scalable=no. Users can still scale text via traps 1/2; if you rely on zoom instead, setzoomEnabled: trueand dropuser-scalable=no. - SPA navigation is silent. Route changes do not trigger a page-load announcement. After navigation set
document.title, move focus to the main heading (<h1 tabindex="-1">), or update a polite live region. Do not useScreenReader.speakas the primary mechanism: it only speaks when a screen reader is active and bypasses the user's verbosity settings. - Native views under or over the WebView.
@capacitor/google-mapsrenders a native map behind a transparent WebView region; camera preview plugins do the same. The screen reader sees the WebView, not the native view. Provide an accessible alternative (list of markers, text summary, capture button with label) in HTML. - Native plugin UI. Dialogs, action sheets, share sheets, pickers from official plugins are native and accessible by default; custom native screens in your own plugins need
accessibilityLabel/contentDescription(seereferences/native.md). - Touch targets. Apple HIG minimum 44x44 pt; Material 48x48 dp; WCAG 2.2 2.5.8 minimum 24x24 CSS px. Icon buttons need padding, not just a small SVG.
- Motion and contrast.
prefers-reduced-motionandprefers-contrastmedia queries work in both WebViews. Disable parallax/auto-playing transitions under reduce motion; test Increase Contrast. - Status changes. Toasts (
@capacitor/toastis native and announced), inline errors, spinners: userole="status"/aria-live="polite"for web toasts andaria-busyon loading regions; userole="alert"only for errors. - Focus after native round-trips. After a native modal (camera, share, auth browser) closes, focus may land on
<body>. Restore focus to the triggering control onappStateChange/promise resolution.
Verification
- axe: zero critical/serious violations on each audited route.
- VoiceOver (iOS) and TalkBack (Android): every control has a spoken name, role, and state; swipe order follows visual order; route change is announced or focus moves to heading.
- Largest text:
xcrun simctl ui booted content_size accessibility-extra-extra-extra-largeandadb shell settings put system font_scale 2.0; no clipped or overlapping text, no horizontal scroll on body. - Grep:
grep -rnE "user-scalable=no|maximum-scale=1" index.html src/andgrep -rn "outline: *none\|outline: *0" src/(each must have a:focus-visiblereplacement). - Reset after testing:
adb shell settings put system font_scale 1.0,xcrun simctl ui booted content_size large.
Error Handling
| Symptom / message | Fix |
ScreenReader.isEnabled rejects/unavailable on web | Not supported on web (screen readers cannot be detected); guard with Capacitor.isNativePlatform(). |
speak throws on web | Browser lacks SpeechSynthesis; only call on native or feature-detect 'speechSynthesis' in window. |
"TextZoom" plugin is not implemented on web | text-zoom is native only; skip on web. |
| Text zoom has no effect on iPad | Set ios.preferredContentMode: 'mobile'. |
| Text scaled twice on iOS | Using both -apple-system-body and TextZoom; keep one. |
| VoiceOver reads "button" with no name | Icon-only control missing aria-label or visible text. |
References
Only load when the topic is in play:
references/testing.md: VoiceOver/TalkBack gestures, Accessibility Inspector, Android Accessibility Scanner, adb/simctl setting commands, axe in Playwright, per-screen checklist.references/native.md: Swift/Kotlin accessibility APIs for custom native plugin views, posting announcements from native code.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

