Disable text selection and the magnifier lens in Capacitor iOS apps
@capgo/capacitor-textinteraction gives you one call to switch text interaction on or off for the Capacitor WebView on iOS. When it is off, long-pressing text no longer selects it, shows the copy callout, or brings up the magnifier lens that iOS 15 reintroduced. Your web app stops feeling like a web page inside a native shell.
Under the hood the plugin sets WKPreferences.isTextInteractionEnabled on the app's WKWebView. It changes nothing else.
When to use it
- Games, kiosks and drawing apps where long-press and drag gestures should never select text.
- Custom long-press menus that clash with the native selection handles and callout.
- Media players, maps and carousels where a slow swipe accidentally triggers the loupe.
- Branded, app-like UI where selectable labels and buttons break the native feel.
Keep text interaction on for screens where users read long content they may want to copy, or where they fill in forms.
Install
bun add @capgo/capacitor-textinteraction
bunx cap sync
No Info.plist keys, permissions or capacitor.config.ts entries are needed.
| Plugin version | Capacitor version | Maintained |
|---|---|---|
| v8.x | v8.x | Yes |
| v7.x | v7.x | On demand |
| v6.x and older | v6.x and older | No |
Disable text interaction on app start
import { Capacitor } from '@capacitor/core';
import { TextInteraction } from '@capgo/capacitor-textinteraction';
if (Capacitor.getPlatform() === 'ios') {
const { success } = await TextInteraction.toggle({ enabled: false });
if (!success) console.warn('Text interaction could not be changed on this device');
}
Always pass enabled explicitly. The native side treats a missing value as false.
Re-enable it before users type
While text interaction is off, <input>, <textarea> and contenteditable elements stop accepting input. Turn it back on for any screen with a form, then turn it off again when the user leaves.
import { Capacitor } from '@capacitor/core';
import { TextInteraction } from '@capgo/capacitor-textinteraction';
const isIos = Capacitor.getPlatform() === 'ios';
export async function setTextInteraction(enabled: boolean) {
if (!isIos) return false;
const { success } = await TextInteraction.toggle({ enabled });
return success;
}
// Entering a login, search or checkout screen
await setTextInteraction(true);
// Leaving it
await setTextInteraction(false);
With a router, call setTextInteraction(true) in the enter hook of routes that contain inputs (for example Vue Router beforeEnter, a React useEffect, or Angular ionViewWillEnter) and setTextInteraction(false) when leaving them.
Plugin vs CSS
You can hide most selection with CSS:
body {
-webkit-user-select: none;
user-select: none;
-webkit-touch-callout: none;
}
input,
textarea,
[contenteditable] {
-webkit-user-select: text;
user-select: text;
}
CSS works per element, so anything you forget stays selectable, and it does not change how the WebView itself handles long-press. The plugin works at the WebView level: one call covers every screen, including the magnifier lens. Many apps use both: the plugin for app-like screens and CSS for fine control inside screens where text interaction stays on.
API reference
toggle(options)
toggle(options: { enabled: boolean }): Promise<{ success: boolean }>
Turns text interaction on or off for the Capacitor WebView.
enabled:truerestores selection, the callout and the magnifier lens.falsedisables them.success:truewhen the change was applied (iOS 14.5+ with a WebView available).falseon Android and when no WebView is available.
getPluginVersion()
getPluginVersion(): Promise<{ version: string }>
Returns the native plugin version. Returns web in the browser.
Platform behavior
| Platform | Behavior |
|---|---|
| iOS 14.5+ | Sets isTextInteractionEnabled on the WKWebView. Applies to all pages until toggled again. |
| Android | No-op. Resolves { success: false }. Use CSS if you need to limit selection. |
| Web | toggle throws an unimplemented error. Guard calls with Capacitor.getPlatform(). |
Troubleshooting
- Inputs stopped working. Text interaction is still disabled. Call
toggle({ enabled: true })before the form is shown. - Nothing changes on Android. Expected. The plugin only supports iOS.
TextInteraction.toggle is not available on web. The call ran in the browser or during development in a desktop browser. Wrap it in a platform check.- Selection comes back after restarting the app. Each launch creates a new WebView with text interaction enabled. Call
toggle({ enabled: false })during startup.
Related plugins
- Privacy Screen hides app content in the iOS app switcher and blocks Android screenshots.
- Home Indicator hides the iOS home indicator for immersive screens.
- Screen Orientation locks and reads screen orientation.
- Browse all Capacitor plugins by Capgo.
Ship the change without an App Store review
Toggling text interaction is JavaScript. Once the plugin is in your native build, you can change where and when it runs with a Capgo live update instead of waiting for App Store review.
Full reference
- Docs: Text Interaction plugin documentation
- Getting started: Install and API guide
- Source: Cap-go/capacitor-textinteraction on GitHub