JavaScript: Scroll to selection after using textarea.setSelectionRange in Chrome

This is a code inspired by the Matthew Flaschen's answer.

/**
 * Scroll textarea to position.
 *
 * @param {HTMLInputElement} textarea
 * @param {Number} position
 */
function scrollTo(textarea, position) {
    if (!textarea) { return; }
    if (position < 0) { return; }

    var body = textarea.value;
    if (body) {
        textarea.value = body.substring(0, position);
        textarea.scrollTop = position;
        textarea.value = body;
    }
}

Basically, the trick is to truncate the textarea, scroll to the end, then restore the second part of the text.

Use it as follows

var textarea, start, end;
/* ... */

scrollTo(textarea, end);
textarea.focus();
textarea.setSelectionRange(start, end);

A lot of answers, but the accepted one doesn't consider line breaks, Matthew Flaschen didn't add the solution code, and naXa answer has a mistake. The simplest solution code is:

textArea.focus();

const fullText = textArea.value;
textArea.value = fullText.substring(0, selectionEnd);
textArea.scrollTop = textArea.scrollHeight;
textArea.value = fullText;

textArea.setSelectionRange(selectionStart, selectionEnd);

Here is a simple and efficient solution in pure JavaScript:

// Get the textarea
var textArea = document.getElementById('myTextArea');

// Define your selection
var selectionStart = 50;
var selectionEnd = 60;
textArea.setSelectionRange(selectionStart, selectionEnd);

// Mow let’s do some math.
// We need the number of characters in a row
var charsPerRow = textArea.cols;

// We need to know at which row our selection starts
var selectionRow = (selectionStart - (selectionStart % charsPerRow)) / charsPerRow;

// We need to scroll to this row but scrolls are in pixels,
// so we need to know a row's height, in pixels
var lineHeight = textArea.clientHeight / textArea.rows;

// Scroll!!
textArea.scrollTop = lineHeight * selectionRow;

Put this in a function, extend the prototype of JavaScript's Element object with it, and you're good.


You can see how we solved the problem in ProveIt (see highlightLengthAtIndex). Basically, the trick is to truncate the textarea, scroll to the end, then restore the second part of the text. We also used the textSelection plugin for consistent cross-browser behavior.