Scenario

WebKit contenteditable Focus Bug

A known bug in WebKit browsers prevents focus from transferring correctly from contenteditable elements to non-editable elements. A workaround involves using a hidden input field to manage focus transitions.

focus
Scenario ID
scenario-webkit-focus-bug

Details

Overview

A known bug in WebKit-based browsers (Safari, Chrome) prevents focus from transferring correctly from contenteditable elements to non-editable elements. When attempting to programmatically move focus from a contenteditable element to another element, the focus may not transfer properly, causing the contenteditable element to continue accepting input.

Impact

  • Focus Management Failure: Cannot reliably transfer focus away from contenteditable elements
  • Input Interception: User input continues to go to contenteditable even after blur
  • UI Confusion: Users may type in wrong locations
  • Accessibility Issues: Screen readers and keyboard navigation may malfunction

Technical Details

The issue occurs when:

  1. A contenteditable element has focus
  2. Code attempts to transfer focus to another element (e.g., a button, input field, or non-editable div)
  3. WebKit does not properly release focus from the contenteditable element
  4. The contenteditable element continues to accept input even though it should have lost focus

Browser Comparison

  • Safari (WebKit): This issue occurs
  • Chrome (Blink/WebKit-based): May have similar issues
  • Firefox (Gecko): Not affected
  • Edge (Chromium): May have similar issues

Workarounds

Hidden Input Field Workaround

// Create a hidden input field for focus management
const hiddenInput = document.createElement('input');
hiddenInput.type = 'text';
hiddenInput.style.position = 'absolute';
hiddenInput.style.left = '-9999px';
hiddenInput.style.opacity = '0';
hiddenInput.style.pointerEvents = 'none';
document.body.appendChild(hiddenInput);

function transferFocusFromContentEditable(targetElement) {
  const editor = document.querySelector('[contenteditable]');
  
  // First, blur the contenteditable
  editor.blur();
  
  // Use hidden input as intermediate step
  hiddenInput.focus();
  
  // Then transfer to target
  setTimeout(() => {
    targetElement.focus();
  }, 0);
}

Force Blur with Selection Clear

function forceBlurContentEditable(editor) {
  // Clear selection
  const selection = window.getSelection();
  selection.removeAllRanges();
  
  // Blur the element
  editor.blur();
  
  // Force focus on body to ensure contenteditable loses focus
  document.body.focus();
  
  // Then focus target element
  setTimeout(() => {
    targetElement.focus();
  }, 10);
}
  • 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-0553-webkit-focus-bug-en macOS 11+ Desktop Any Safari 14+ 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, focus

autofocus attribute does not work on contenteditable

The autofocus attribute, which automatically focuses form inputs on page load, does not work on contenteditable elements. There is no built-in way to automatically focus a contenteditable region when a page loads.

1 case
Tags: focus

Programmatic focus selects all content

In Chrome and Safari, calling focus() on a contenteditable div can select the entire content instead of placing the cursor at the beginning, as observed in Firefox and IE.

1 case

Comments & Discussion

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