Text caret invisible on position:relative elements (Chrome macOS)
OS: macOS 13+ · Device: Desktop (Mac) Any · Browser: Chrome 120+ · Keyboard: English (QWERTY)
Open case →Scenario
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.
When editing content inside an element that has position:relative CSS property, the text caret (cursor) is invisible and provides no visual feedback of the insertion point.
This issue occurs when:
position:relative stylingWebKit’s text caret rendering fails when:
position:relativeThe position:relative property creates a new positioning context that breaks the caret rendering algorithm in WebKit-based browsers.
Remove position:relative:
.editable-container {
position: static; /* or remove position property */
}
Use position:static instead:
.editable-container {
position: static;
}
Move position:relative to ancestor element:
/* Make wrapper relative, keep editable static */
.wrapper {
position: relative;
}
.editable {
position: static;
}
Use caret-color property (may help but not complete fix):
[contenteditable] {
caret-color: black; /* May work in some browsers */
}
Provide custom caret element:
// Create custom caret indicator
const caret = document.createElement('span');
caret.className = 'custom-caret';
caret.style.cssText = `
position: absolute;
width: 2px;
height: 20px;
background: black;
animation: blink 1s infinite;
`;
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-0272-caret-invisible-relative-chrome-macos-en | macOS 13+ | Desktop (Mac) Any | Chrome 120+ | English (QWERTY) | draft |
| ce-0273-caret-invisible-relative-firefox-windows-en | Windows 10/11 | Desktop Any | Firefox 120+ | English (QWERTY) | draft |
This matrix shows which browser and OS combinations have documented cases for this scenario. Click on a cell to view the specific case.
| Browser | Windows | macOS |
|---|---|---|
| Chrome | — | |
| Firefox | — |
Open a case to see the detailed description and its dedicated playground.
OS: macOS 13+ · Device: Desktop (Mac) Any · Browser: Chrome 120+ · Keyboard: English (QWERTY)
Open case →OS: Windows 10/11 · Device: Desktop Any · Browser: Firefox 120+ · Keyboard: English (QWERTY)
Open case →Other scenarios that share similar tags or category.
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.
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 setting cursor position using `selection.addRange()` in a contenteditable element, it works correctly in Chrome and Firefox but fails in Safari. The selection "pops out" of intended marker element and moves to the next sibling's text node instead of staying within the marker.
Tapping or moving across contenteditable=false regions on Android can collapse selection or clear the caret in ways that differ from desktop Chrome.
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.
Have questions, suggestions, or want to share your experience? Join the discussion below.