How do I position the caret inside a span element that has no text inside of it yet?
There's a nice trick with zero-width space that you may consider (look at at the code below) and CSS property white-space: pre
that allows spaces to be "visible" when focused.
function makeTextNode() {
return document.createTextNode('') // <-- there a zero-width space between quotes
}
function placeCaretInSpan() {
const range = document.createRange()
const editable = document.getElementById("editable")
const span = editable.querySelector("span")
if (span.childNodes.length === 0) {
span.appendChild(makeTextNode()) // <-- you have to have something in span in order to place caret inside
}
range.setStart(span.childNodes[0], 1) // <-- offset by 1 to be inside SPAN element and not before it
let selection = window.getSelection()
range.collapse(true)
selection.removeAllRanges()
selection.addRange(range)
editable.focus()
}
span {
font-weight: bold;
background: yellow;
}
#editable:focus {
white-space: pre;
}
<div contenteditable="true" id="editable">This should be <span></span> editable.</div>
<button onclick="placeCaretInSpan()">place caret</button>