Scenario

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.

focus
Scenario ID
scenario-focus-selects-all

Details

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.

Observed Behavior

  1. All content selected: Calling focus() selects all content
  2. Cursor not at beginning: Cursor is not placed at the beginning
  3. Browser-specific: This differs from Firefox and IE behavior
  4. User must deselect: User must manually deselect to start typing

Browser Comparison

  • Chrome: All content is selected (this issue)
  • Safari: All content is selected (this issue)
  • Firefox: Cursor is placed at beginning
  • Edge: Cursor is placed at beginning

Impact

  • User confusion: Users may accidentally overwrite content
  • Poor UX: Users must manually deselect before typing
  • Inconsistent behavior: Different from other browsers
  • Workflow interruption: Users must take extra steps to start typing

Workarounds

Manual selection

After focus(), manually set cursor position using Selection API:

function focusEditor() {
  editor.focus();
  
  const selection = window.getSelection();
  const range = document.createRange();
  
  const firstNode = getFirstTextNode(editor);
  if (firstNode) {
    range.setStart(firstNode, 0);
    range.setEnd(firstNode, 0);
  } else {
    range.selectNodeContents(editor);
    range.collapse(true);
  }
  
  selection.removeAllRanges();
  selection.addRange(range);
}

function getFirstTextNode(node) {
  if (node.nodeType === Node.TEXT_NODE) {
    return node;
  }
  
  for (let child of node.childNodes) {
    const textNode = getFirstTextNode(child);
    if (textNode) {
      return textNode;
    }
  }
  
  return null;
}

Range manipulation

Create a range at the beginning and set selection:

editor.addEventListener('focus', () => {
  const selection = window.getSelection();
  if (selection.rangeCount > 0) {
    const range = selection.getRangeAt(0);
    range.collapse(true);
    selection.removeAllRanges();
    selection.addRange(range);
  }
});

Event handling

Handle focus events to reset selection:

editor.addEventListener('focus', (e) => {
  // Reset selection to beginning
  setTimeout(() => {
    const selection = window.getSelection();
    const range = document.createRange();
    range.selectNodeContents(editor);
    range.collapse(true);
    selection.removeAllRanges();
    selection.addRange(range);
  }, 0);
});

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-0304-chrome-safari-focus-selects-all-en macOS 13-14 Desktop or Laptop Any Chrome or Safari 120+ US QWERTY 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: 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

Comments & Discussion

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