Mobile Selection Toolbar

Understanding mobile browser selection toolbars, their differences across platforms, and how to implement custom toolbars.

Overview

When users select text on mobile devices, browsers display a context menu or toolbar with actions like Copy, Paste, and Share. These toolbars vary significantly across browsers, operating systems, and devices. Understanding these differences is crucial for building rich text editors that work well on mobile.

Note: Mobile selection toolbars are system-level UI elements that cannot be fully customized. However, you can detect selection changes and show your own custom toolbar alongside or instead of the default one.

iOS Safari Toolbar

iOS Safari displays a toolbar above the selected text with standard actions.

Default Menu Items

Basic Actions

  • Copy: Copies selected text to clipboard
  • Select All: Selects all text in the contenteditable element
  • Paste: Pastes from clipboard (if clipboard has content)

Formatting Options (contenteditable only)

  • Bold: Applies bold formatting to selected text
  • Italic: Applies italic formatting to selected text
  • Underline: Applies underline formatting to selected text
  • Strikethrough: Applies strikethrough formatting (may not appear in all versions)

⚠️ Formatting options only appear in contenteditable elements, not in regular text inputs.

iOS-Specific Features

  • Look Up: Dictionary lookup (iOS feature)
  • Share: iOS share sheet
  • Define: Dictionary definition

⚠️ iOS-Specific Behavior

iOS Safari characteristics:

  • Toolbar appears above selection (may overlap content)
  • Menu items may vary based on selection context
  • Cannot be fully disabled or customized
  • May interfere with custom toolbars
  • Selection handles are small and may be difficult to use

Android Chrome Toolbar

Android Chrome displays a toolbar with actions that may vary by Android version and device manufacturer.

Default Menu Items

Basic Actions

  • Copy: Copies selected text to clipboard
  • Select All: Selects all text in the contenteditable element
  • Paste: Pastes from clipboard
  • Cut: Cuts selected text (may appear in some contexts)

Formatting Options (contenteditable only)

  • Bold: Applies bold formatting to selected text
  • Italic: Applies italic formatting to selected text
  • Underline: Applies underline formatting to selected text
  • Strikethrough: Applies strikethrough formatting (varies by Android version)

⚠️ Formatting options only appear in contenteditable elements, not in regular text inputs.

Android-Specific Features

  • Web Search: Searches selected text (Android feature)
  • Share: Android share menu
  • Translate: Google Translate (if available)

⚠️ Android-Specific Behavior

Android Chrome characteristics:

  • Toolbar position may vary (above or below selection)
  • Menu items differ by Android version and manufacturer
  • Samsung devices may have additional options
  • Selection handles may overlap with content
  • Virtual keyboard may interfere with toolbar visibility

Browser-Specific Differences

Toolbar Comparison

Browser Position Menu Items Customizable
iOS Safari Above selection Copy, Select All, Paste, Bold, Italic, Underline, Look Up, Share, Define No (system-level)
Android Chrome Above or below Copy, Select All, Paste, Cut, Bold, Italic, Underline, Web Search, Share, Translate No (system-level)
Android Firefox Above selection Copy, Select All, Paste, Bold, Italic, Underline, Share No (system-level)
Samsung Internet Above selection Copy, Select All, Paste, Bold, Italic, Underline, Share, Samsung-specific options No (system-level)

⚠️ Critical: Toolbar Cannot Be Fully Disabled

System-level toolbars cannot be completely disabled:

  • CSS -webkit-touch-callout: none may prevent some toolbars on iOS, but not all
  • Setting user-select: none prevents selection entirely
  • Preventing contextmenu event may not work on all browsers
  • Best approach: Show custom toolbar alongside default, or design UI to work with default toolbar

Formatting Menu Items

In contenteditable elements, mobile browsers may show formatting options (Bold, Italic, Underline) in the selection toolbar. These options vary by browser and OS version.

⚠️ Critical: Formatting Only in contenteditable

Formatting options only appear in contenteditable elements:

  • Regular <input> or <textarea> elements do not show formatting options
  • Only contenteditable elements trigger formatting menu items
  • Formatting options may not appear if selection is collapsed (cursor only)

Formatting Options by Browser

iOS Safari

  • Bold: Appears when text is selected in contenteditable
  • Italic: Appears when text is selected
  • Underline: Appears when text is selected
  • Formatting options may vary by iOS version
  • iPad may show additional formatting options

Android Chrome

  • Bold: Appears in contenteditable elements
  • Italic: Appears in contenteditable elements
  • Underline: Appears in contenteditable elements
  • Strikethrough: May appear in newer Android versions
  • Formatting options may vary by Android version and device manufacturer

Android Firefox

  • Bold: Appears in contenteditable elements
  • Italic: Appears in contenteditable elements
  • Underline: Appears in contenteditable elements
  • May have fewer formatting options than Chrome

⚠️ Formatting Behavior Differences

Formatting behavior varies:

  • Formatting may apply to entire selected text or toggle existing formatting
  • Some browsers may show formatting state (bold/not bold) in toolbar
  • Formatting shortcuts (if any) may differ from desktop
  • Formatting during IME composition may not work (especially on macOS with Korean IME)

Select All Behavior

The "Select All" option in mobile toolbars selects all content within the contenteditable element, not just the visible text.

  • Scope: Selects all text in the contenteditable element, including nested elements
  • Behavior: Creates a Range that spans from first to last text node
  • Cross-element: May select across multiple block elements (p, div, etc.)
  • Browser differences: Some browsers may include or exclude certain elements differently

Note: "Select All" behavior may differ from desktop keyboard shortcut (Cmd/Ctrl + A). On mobile, it's triggered through the toolbar menu, which may have different behavior than the keyboard shortcut.

OS & Device-Specific Differences

iOS

  • iOS Version: Menu items and formatting options may differ between iOS versions
  • iPad vs iPhone: Toolbar behavior and formatting options may differ on larger screens
  • Accessibility: VoiceOver may affect toolbar interaction and menu item availability
  • Split View: Toolbar positioning may change in split-screen mode
  • Formatting: iPad may show more formatting options than iPhone

Android

  • Android Version: Menu items and formatting options vary by Android version (e.g., Android 10 vs Android 13)
  • Manufacturer: Samsung, Xiaomi, etc. may add custom menu items or modify formatting options
  • Device Size: Tablet vs phone may have different toolbar layouts and formatting options
  • Custom ROMs: Custom Android ROMs may modify toolbar behavior and menu items
  • Keyboard Apps: Some keyboard apps (Gboard, Samsung Keyboard) may add their own formatting options

Implementing Custom Toolbars

While you cannot fully replace the system toolbar, you can detect selection changes and show your own custom toolbar. Here are common approaches:

// Show custom toolbar on selection
let customToolbar = null;

document.addEventListener('selectionchange', () => {
  const selection = window.getSelection();
  if (selection.rangeCount > 0 && !selection.isCollapsed) {
    const range = selection.getRangeAt(0);
    const rects = range.getClientRects();
    
    if (rects.length > 0) {
      const rect = rects[0];
      showCustomToolbar(rect);
    }
  } else {
    hideCustomToolbar();
  }
});

function showCustomToolbar(rect) {
  if (!customToolbar) {
    customToolbar = document.createElement('div');
    customToolbar.className = 'custom-toolbar';
    customToolbar.innerHTML = `
      <button onclick="formatBold()">Bold</button>
      <button onclick="formatItalic()">Italic</button>
      <button onclick="copyText()">Copy</button>
    `;
    document.body.appendChild(customToolbar);
  }
  
  // Position toolbar above selection
  customToolbar.style.display = 'block';
  customToolbar.style.position = 'fixed';
  customToolbar.style.top = (rect.top - 50) + 'px';
  customToolbar.style.left = rect.left + 'px';
}

function hideCustomToolbar() {
  if (customToolbar) {
    customToolbar.style.display = 'none';
  }
}

⚠️ Positioning Challenges

Toolbar positioning is complex on mobile:

  • System toolbar may overlap your custom toolbar
  • Virtual keyboard may push toolbars off-screen
  • Viewport changes (zoom, rotation) affect positioning
  • Multi-line selections require different positioning logic
  • Use getClientRects() for accurate selection position

Best Practices

  • Position above selection: Place custom toolbar above selection to avoid overlap with system toolbar
  • Hide on scroll: Hide custom toolbar when user scrolls to avoid UI clutter
  • Touch-friendly buttons: Make toolbar buttons large enough for touch (minimum 44x44px)
  • Handle viewport changes: Reposition toolbar on orientation change or keyboard show/hide
  • Test on real devices: Emulators may not accurately represent toolbar behavior

Disabling Default Toolbar (Limited)

Attempting to disable the default toolbar has limited success. Here are approaches that may work in some browsers:

// Disable default selection toolbar (may not work in all browsers)
element.style.userSelect = 'none'; // Prevents selection entirely

// Or allow selection but try to prevent toolbar
element.addEventListener('contextmenu', (e) => {
  e.preventDefault(); // May prevent some toolbars
});

// CSS approach
// .contenteditable {
//   -webkit-user-select: text;
//   -webkit-touch-callout: none; /* iOS Safari - disable callout menu */
//   user-select: text;
// }

⚠️ Limitations

These methods have limitations:

  • -webkit-touch-callout: none only works on iOS Safari, and may not prevent all toolbars
  • Preventing contextmenu may not work on all mobile browsers
  • Setting user-select: none prevents all selection, which breaks text editing
  • Best practice: Design your UI to work with the default toolbar, or show custom toolbar alongside it

Mobile Detection

Detect mobile devices to conditionally show custom toolbars or handle mobile-specific behavior:

// Detect mobile device
function isMobile() {
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
}

// Detect touch capability
function isTouchDevice() {
  return 'ontouchstart' in window || navigator.maxTouchPoints > 0;
}

// Use for conditional toolbar behavior
if (isMobile() || isTouchDevice()) {
  // Show custom toolbar or handle mobile-specific behavior
}

Selection Handle Issues

⚠️ Mobile Selection Handles

Selection handles are problematic on mobile:

  • Size: Handles are small and difficult to grab with fingers
  • Overlap: Handles may overlap with content or toolbar
  • Precision: Touch input is less precise than mouse, making fine adjustments difficult
  • Scrolling: Dragging handles may trigger page scroll instead of selection adjustment
  • Keyboard: Virtual keyboard may cover handles or toolbar

Consider providing alternative selection methods for mobile, such as tap-to-select-word or long-press-to-select-sentence, to improve usability.

Virtual Keyboard Interference

⚠️ Keyboard and Toolbar Conflicts

Virtual keyboard may interfere with toolbars:

  • Keyboard may push toolbar off-screen
  • Toolbar may appear behind keyboard
  • Selection handles may be hidden by keyboard
  • Viewport height changes when keyboard appears/disappears
  • Reposition toolbar when keyboard visibility changes

Testing Recommendations

  • Test on real devices: Emulators may not accurately show toolbar behavior
  • Test multiple browsers: Safari, Chrome, Firefox, Samsung Internet
  • Test different OS versions: iOS 15+, iOS 16+, Android 10+, Android 13+
  • Test different devices: iPhone, iPad, various Android phones and tablets
  • Test with virtual keyboard: Ensure toolbars work when keyboard is visible
  • Test orientation changes: Portrait vs landscape may affect toolbar positioning
  • Test with different keyboard apps: Gboard, Samsung Keyboard, iOS keyboard

Related resources