cap-go/capgo-skills/capacitor-keyboard
Claude Code and agent skill by cap-go/capgo-skills
- community
Checking that the SKILL.md file is still in the repository.
Fixes on-screen keyboard behavior in Capacitor apps with @capacitor/keyboard - iOS `resize` modes (`native` default, `body`, `ionic`, `none`), `keyboardWillShow`/`keyboardDidShow` heights, `setAccessoryBarVisible`, `setScroll`, `style` (`DARK`/`LIGHT`/`DEFAULT`), `autoBackdropColor` (8.0.4+), Android edge-to-edge/SystemBars interaction (drop legacy `resizeOnFullScreen` on Capacitor 8), iOS 26 fixes, and iOS input auto-zoom. Use when inputs are hidden behind the keyboard, the WebView jumps or le…
Install
npx vskill@latest install cap-go/capgo-skills/capacitor-keyboardSKILL.md
Keyboard Handling in Capacitor
When to Use
TRIGGER when:
- Focused input is covered by the keyboard, or the page scrolls unexpectedly
- Chat composer / fixed footer does not stick to the keyboard
- White or black band above the keyboard (Android 15+ edge-to-edge, iOS backdrop)
100vh/dvhlayout collapses when the keyboard opens- iOS zooms into inputs, or the QuickType/accessory bar looks wrong
- Keyboard events never fire or fire twice
Do not use:
- Notch / home-indicator / status-bar padding:
safe-area-handling - Ionic
ion-input,ion-footerstyling:ionic-design - Labels, focus order, screen readers:
capacitor-accessibility
Platform model (the key decision)
| iOS | Android | ||
|---|---|---|---|
| Who resizes | Plugin, per resize mode | OS + WebView; resize config is ignored | |
| Events | keyboardWillShow before animation, keyboardDidShow after | Will/Did fire almost together | |
| JS control | setResizeMode, getResizeMode, setScroll, setStyle, setAccessoryBarVisible (iPhone only) | show() (Android only), hide() |
iOS resize modes (KeyboardResize enum):
| Mode | Effect | Use when | |
|---|---|---|---|
native (default) | Whole WebView shrinks; vh units change | Plain web apps; simplest | |
body | Only <body> height changes; vh unchanged | Layouts that rely on stable vh | |
ionic | Only ion-app resizes | Ionic Framework apps only | |
none | Nothing resizes; you position with keyboard height | Custom chat UIs, full control |
Workflow
- Inspect:
capacitor.config.*plugins.Keyboard,@capacitor/keyboardversion (8.0.4+ includes iOS 26 and Android SystemBars fixes), whether Ionic is used,@capacitor/status-bar/ SystemBars config, and the failing screen's CSS (position: fixed,100vh). - Reproduce on a device (simulators often use a hardware keyboard: iOS Simulator -> I/O -> Keyboard -> Toggle Software Keyboard).
- Pick the iOS resize mode from the table; set it in config, not at runtime, unless one screen needs a different mode.
- Fix Android separately (below).
- Verify.
Config
String values in JSON config are uppercase for style ("DARK"), lowercase for resize ("body").
Custom positioning (resize: none or chat UIs)
Use max(), not +: while the keyboard is up the home-indicator inset is already covered.
Android notes
- Android 15+ (targetSdk 35) enforces edge-to-edge; Android 16 (targetSdk 36, Capacitor 8 default) removes the opt-out. The WebView now draws under system bars, so the keyboard inset must be handled.
@capacitor/keyboard7.0.2 fixed white space above the keyboard on Android 15+, and 8.0.3 fixed the interaction with the SystemBars core plugin. Update the plugin before writing workarounds. resizeOnFullScreen: truewas the Capacitor <= 7 workaround for fullscreen / overlaid status bar. On Capacitor 8+ the SystemBars core plugin handles IME insets and logs `You should omitKeyboard.resizeOnFullScreenin yourcapacitor.config.json. Other values can lead to unexpected behavior.unlessSystemBars.insetsHandlingisdisable`. Remove it.- Do not add
android:windowSoftInputMode="adjustPan"to fix overlap; it pans the whole window and breaks fixed headers. The template omits it (default resize behavior). env(keyboard-inset-height)andinteractive-widgetviewport meta are Chromium features; test on the target Android System WebView version before relying on them, and never on iOS.
iOS notes
- Inputs with computed
font-size< 16px make iOS zoom on focus. Usefont-size: 16px(or larger) on inputs; do not disable user zoom globally (maximum-scale=1) as it hurts accessibility. setAccessoryBarVisible({ isVisible: false })hides the prev/next/done bar on iPhone; it has no effect on iPad.setScroll({ isDisabled: true })stops the WebView scroll view from bouncing when the keyboard opens; pair withresize: nonefor custom layouts.- iOS 26 keyboard regressions and the iPad Magic Keyboard black QuickType bar were fixed in
@capacitor/keyboard8.0.4. If a black/white band appears behind the keyboard, setautoBackdropColor: 'auto'(usesbackgroundColorfrom config, else the DOM body background) or'dom'.
Verification
npx cap syncand run on a physical iPhone and an Android 15+/16 device.- For each form screen: focus first and last input; the focused field stays visible; footer sits on the keyboard; no gap above the keyboard; rotating with the keyboard open keeps layout.
- Dismiss via swipe/back button:
keyboardWillHidefires and--kbreturns to 0. - iOS: confirm no zoom on focus; accessory bar state matches the design.
- Check versions:
npm ls @capacitor/keyboard @capacitor/core.
Error Handling
| Symptom / message | Cause | Fix | |
|---|---|---|---|
"Keyboard" plugin is not implemented on web or "Keyboard.setAccessoryBarVisible()" is not implemented on android | Plugin/method unavailable on that platform | Guard with Capacitor.getPlatform() === 'ios' | |
show() does nothing on iOS | show() is Android only | Focus an input from a user gesture instead | |
| Footer floats in the middle after keyboard closes (Android) | WebView height not reset when keyboard hides without animation | Update to @capacitor/keyboard 8.0.4+ | |
| White band above keyboard on Android 15+ | Edge-to-edge insets + old plugin | Update plugin (7.0.2+ / 8.0.3+); on Capacitor 8 remove resizeOnFullScreen | |
Logcat `SystemBars: You should omit Keyboard.resizeOnFullScreen ...` | Legacy config fighting SystemBars inset handling | Delete resizeOnFullScreen from config | |
vh-based screen shrinks on iOS | resize: native changes viewport | Switch to body or none | |
| Ionic content jumps twice | resize: native/body plus Ionic's own handling | Use resize: 'ionic' | |
| Listeners fire twice after navigation | Listener added per page mount, never removed | Keep the returned handle and await handle.remove() on unmount | |
| Black QuickType bar on iPad with hardware keyboard | Pre-8.0.4 plugin bug | Update plugin |
Resources
- Keyboard plugin API: https://capacitorjs.com/docs/apis/keyboard
- Plugin changelog: https://github.com/ionic-team/capacitor-keyboard/blob/main/CHANGELOG.md
- System Bars (edge-to-edge): https://capacitorjs.com/docs/apis/system-bars
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingplugins/capacitor-features/skills/capacitor-keyboard/SKILL.md
Popularity
- Repository stars
- 20
- Repository forks
- 3
- Repository npm downloads, 7 days
- 6
- 7-day trend score
- 21
Stars and forks are for the whole GitHub repository, not this skill alone. Downloads are for the repository's npm package. Refreshed 17 Mar 2026, 7 months ago.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/cap-go/capgo-skills/capacitor-keyboard)