3

I have <textarea> element and create range inside it:

  • Create new range via document.createRange()
  • Get the only child node of <textarea> via textarea.childNodes[0]
  • Set range start and range end via range.setStart and range.setEnd

Then I call range.getBoundingClientRect():

let textarea = document.querySelector('textarea');
let node = textarea.childNodes[0];

let range = document.createRange();
range.setStart(node, 3);
range.setEnd(node, 5);
console.log(range.getBoundingClientRect());
<textarea>aa bb cc</textarea>

But I receive ClientRect object with all zero fields, that is left = top = width = height = 0. Why these fields are zeros?


Note that all works fine if I replace <textarea> with usual div:

let textarea = document.querySelector('div');
let node = textarea.childNodes[0];

let range = document.createRange();
range.setStart(node, 3);
range.setEnd(node, 5);
console.log(range.getBoundingClientRect());
<div>aa bb cc</div>
diralik
  • 6,391
  • 3
  • 28
  • 52

2 Answers2

2

<textarea> is a replacement element

Objects inserted using the CSS content property are anonymous replaced elements. They are "anonymous" because they don't exist in the HTML markup.

guest271314
  • 1
  • 15
  • 104
  • 177
  • Thanks for answer, but why if I replace – diralik Oct 01 '17 at 20:31
  • 1
    ` – guest271314 Oct 01 '17 at 20:40
  • Thank you. So, there is no simple way to modify my code in order to it returns non zero for textarea? – diralik Oct 01 '17 at 20:44
  • You can use `
    ` element with `contentEditiable` attribute set
    – guest271314 Oct 01 '17 at 20:45
  • This doesn't seem accurate? ` – Simon Buchan Sep 16 '21 at 04:56
0

Here is an example how to do it:

https://jh3y.medium.com/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a

You need to create a div, copy all styles of the input element into that div, copy text up to the selection into that div, add a span inside that div with the selection and then you can measure this span relative to the div before removing the div again.

Christian
  • 2,903
  • 4
  • 31
  • 34