Scenario

Input Events Fire on Focus/Blur in Chrome Android

In Chrome on Android, input events may fire when a contenteditable element gains or loses focus, even without content changes. This behavior can lead to unintended side effects in applications relying on input events for content modification detection.

mobile
Scenario ID
scenario-chrome-android-focus-blur-input

Details

Overview

In Chrome on Android, input events may fire when a contenteditable element gains or loses focus, even without any actual content changes. This behavior can lead to unintended side effects in applications that rely on input events to detect content modifications.

Impact

  • False Positive Events: Input events fire without actual content changes
  • Unintended Side Effects: Applications may trigger save operations, validation, or other actions unnecessarily
  • Performance Issues: Unnecessary processing triggered by false input events
  • User Experience: Applications may behave unexpectedly

Technical Details

The issue occurs when:

  1. A contenteditable element gains focus (user taps on it)
  2. An input event fires even though no content was changed
  3. Similarly, when the element loses focus, an input event may fire
  4. Applications listening to input events may trigger unnecessary actions

Browser Comparison

  • Chrome Android: This issue occurs
  • Chrome Desktop: Not affected
  • Firefox Android: Not affected
  • Safari iOS: Not affected

Workarounds

Filter False Input Events

const editor = document.querySelector('[contenteditable]');
let lastContent = editor.innerHTML;
let isFocusing = false;
let isBlurring = false;

editor.addEventListener('focus', () => {
  isFocusing = true;
  lastContent = editor.innerHTML;
  
  // Reset flag after a short delay
  setTimeout(() => {
    isFocusing = false;
  }, 100);
});

editor.addEventListener('blur', () => {
  isBlurring = true;
  
  // Reset flag after a short delay
  setTimeout(() => {
    isBlurring = false;
  }, 100);
});

editor.addEventListener('input', (e) => {
  // Ignore input events during focus/blur
  if (isFocusing || isBlurring) {
    return;
  }
  
  // Check if content actually changed
  const currentContent = editor.innerHTML;
  if (currentContent === lastContent) {
    // Content didn't change, ignore this event
    return;
  }
  
  // Content actually changed, process the event
  lastContent = currentContent;
  handleContentChange(currentContent);
});

Use MutationObserver Instead

const editor = document.querySelector('[contenteditable]');
let isUserInput = false;

// Track user input
editor.addEventListener('beforeinput', () => {
  isUserInput = true;
});

editor.addEventListener('input', () => {
  isUserInput = false;
});

// Use MutationObserver to detect actual DOM changes
const observer = new MutationObserver((mutations) => {
  // Only process if it was user input
  if (isUserInput) {
    handleContentChange(editor.innerHTML);
  }
});

observer.observe(editor, {
  childList: true,
  subtree: true,
  characterData: true
});

Debounce Input Events

const editor = document.querySelector('[contenteditable]');
let inputTimeout;

editor.addEventListener('input', (e) => {
  // Clear previous timeout
  clearTimeout(inputTimeout);
  
  // Debounce input events
  inputTimeout = setTimeout(() => {
    const currentContent = editor.innerHTML;
    handleContentChange(currentContent);
  }, 150);
});
  • Case IDs will be added as cases are created for specific environment combinations

References

Scenario flow

Visual view of how this scenario connects to its concrete cases and environments. Nodes can be dragged and clicked.

React Flow mini map

Variants

Each row is a concrete case for this scenario, with a dedicated document and playground.

Case OS Device Browser Keyboard Status
ce-0312-chrome-android-focus-blur-input-en Android 10+ Mobile Any Chrome for Android 90+ Any draft

Cases

Open a case to see the detailed description and its dedicated playground.

Related Scenarios

Other scenarios that share similar tags or category.

Tags: chrome, android, mobile

enterkeyhint attribute does not work on contenteditable

The enterkeyhint attribute, which controls the label on the Enter key on mobile keyboards, does not work on contenteditable elements. The Enter key label remains the default regardless of the attribute value.

1 case
Tags: chrome, android

Samsung Keyboard Text Prediction Issues in contenteditable

Samsung keyboard's text prediction feature causes various input event handling issues in contenteditable elements on Android Chrome, including insertCompositionText events, missing getTargetRanges(), selection mismatches, and combined event.data when typing adjacent to links or formatted elements.

1 case

Comments & Discussion

Have questions, suggestions, or want to share your experience? Join the discussion below.