Let's assume that you have a <textarea>
component and that you want to get the caret position of it in pixels:
html<textarea onkeyup = 'getCaretPos(event)' id = 'textarea' rows = '1'></textarea>
The idea is to create a dummy element and to play with the dimensions/coordinates of it using getClientsRects()
and getBoundingClientRect()
.
javascriptconst getCaretPos = (e) => { // Getting the textarea element let textarea = document.getElementById('textarea'); // Adjusting textarea to prevent scrolling textarea.style.height = `${e.target.scrollHeight}px` // Appending element to the DOM after textarea textarea.insertAdjacentHTML('afterend', `<span id = 'dummy'>${textarea.value}</span>`); // Getting position info of the rectangles inside dummy element let rectangles = document.getElementById('dummy').getClientRects(); let last = rectangles[rectangles.length - 1]; // Getting position info of the textarea let text = document.getElementById('textarea').getBoundingClientRect(); // Setting coordinates let x = last.x + last.width; let y = text.y + text.height - last.height; // Removing dummy dummy.remove(); // Returning variables return [x, y]; }
And here is the CSS:
CSSbody{ width: 200px; } #dummy, #textarea{ box-sizing: border-box; font: 14px/1 monospace; border: 1px solid #999; white-space: pre-wrap; margin: 0; overflow: hidden; width: 100%; }
You could add a function to draw a marker on top of the caret to verify if the returning variables are correct.
Example:
javascriptconst drawSquare = (x, y) => { // Deleting previous square; if(document.getElementById('square')) document.getElementById('square').remove(); // Inserting new one textarea.insertAdjacentHTML('afterend', `<div id = 'square'></div>`); // Modifying position of it document.getElementById('square').style.left = `${x}px`; document.getElementById('square').style.top = `${y}px`; }
And here is the CSS:
CSS#square{ background: #4CAF50; border-radius: 50%; height: 5px; position: absolute; width: 5px; }
You can see the full example at CodePen.
Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.