RTL scrolling and caret misalignment in contenteditable
OS: Windows 11 · Device: Desktop Any · Browser: Chrome 124.0 · Keyboard: Arabic/Hebrew (RTL)
Open case →Scenario
Right-to-left (RTL) and mixed-direction text in contenteditable causes caret misalignment, scroll failures, and select-all behavior that differs from LTR and from spec.
When contenteditable contains RTL (Arabic, Hebrew) or mixed LTR/RTL text, browsers diverge in how they handle caret position, automatic scrolling, selection direction, and Ctrl+A (Select All). Editors that support RTL languages cannot rely on consistent behavior across Blink, WebKit, and Gecko.
overflow: auto, the caret may move outside the visible area; scrollLeft is not updated correctly for the logical “end” of RTL text (visually left).Code to observe scroll/caret in RTL:
const editor = document.querySelector('[contenteditable="true"]');
editor.addEventListener('input', () => {
const sel = window.getSelection();
if (!sel.rangeCount) return;
const range = sel.getRangeAt(0);
const rect = range.getBoundingClientRect();
const containerRect = editor.getBoundingClientRect();
// In RTL, logical end is on the left; scroll may not follow
if (rect.left < containerRect.left) {
editor.scrollLeft += (rect.left - containerRect.left) - 10;
}
});
getBoundingClientRect() and adjust scrollLeft when the caret leaves the visible area.dir explicitly: Use dir="rtl" (or auto) on the editable container and blocks so the engine computes BiDi correctly.input or selectionchange, read getRangeAt(0) and optionally collapse to a known-good position if detection heuristics indicate misplacement.dir on the contenteditable root when supporting RTL.scrollLeft === 0 means “start” in RTL; logical start is on the right.Visual view of how this scenario connects to its concrete cases and environments. Nodes can be dragged and clicked.
Each row is a concrete case for this scenario, with a dedicated document and playground.
| Case | OS | Device | Browser | Keyboard | Status |
|---|---|---|---|---|---|
| ce-0570 | Windows 11 | Desktop Any | Chrome 124.0 | Arabic/Hebrew (RTL) | confirmed |
Open a case to see the detailed description and its dedicated playground.
OS: Windows 11 · Device: Desktop Any · Browser: Chrome 124.0 · Keyboard: Arabic/Hebrew (RTL)
Open case →Other scenarios that share similar tags or category.
When the browser is zoomed (or content is scaled via CSS transforms), caret position and text selection in contenteditable elements can become inaccurate. Clicking at a certain position places the caret elsewhere, and selection highlights may not match the visual selection.
When a range of text is selected inside a `contenteditable` element, clicking outside the element
When editing content inside an element with `position:relative`, the text caret (cursor) is completely invisible. Text can be typed and appears in the editor, but there's no visual feedback of where the insertion point is located.
On Chrome Mobile for Android, typing certain punctuation characters (commas, colons, semicolons, quotes, etc.) in the middle of a word causes the cursor to jump to the end of the word instead of staying at the insertion point.
When deleting the last character before a non-editable "pill" or tag element (contenteditable="false") in a contenteditable div in Chrome, the caret (cursor) jumps to the end of the entire contenteditable div instead of staying adjacent to the remaining content.
Have questions, suggestions, or want to share your experience? Join the discussion below.