References

Beginner-friendly references for web development, with live, editable examples.

The selectionEnd DOM property

DOM property All modern browsers Updated
In short

selectionEnd is a JavaScript property giving the index just after the selected text in a text field. You set it from script, never in the markup. Use it with selectionStart, as in value.slice(el.selectionStart, el.selectionEnd), to get the selected text.

Overview

selectionEnd is a JavaScript property giving the index just after the selected text in a text field. It lives on text <input> and <textarea> elements and has no HTML attribute form, so you read and write it only from script.

Because it points after the selection, the end index is exclusive. With the value Hello world and the word Hello selected, selectionStart is 0 and selectionEnd is 5, which is exactly what value.slice(0, 5) expects. Subtracting one from the other gives the length of the selection.

With no selection, selectionEnd equals selectionStart and both mark the caret. Setting selectionEnd lower than the current start collapses the selection to the new position, and a number larger than the value's length is clamped to the end. In a textarea, each line break counts as a single character.

Text selected inside a field doesn't always show up through window.getSelection(). MDN notes that it doesn't work on the content of input and textarea elements in Firefox, and it suggests selectionStart and selectionEnd as a workaround. On email and number inputs the property returns null.

Syntax

<label for="notes">Notes</label>
<textarea id="notes">Line one</textarea>
<script>
  const notes = document.getElementById('notes');
  const selected = notes.value.slice(notes.selectionStart, notes.selectionEnd);
  notes.selectionEnd = notes.value.length;
</script>

Values

Value
An integer character offset.

Example

Live example
<label for="md">Select a word, then click Bold</label><br>
<textarea id="md" rows="3" cols="36">Make this word bold</textarea><br>
<button type="button" id="bold">Bold</button>
<script>
document.getElementById('bold').addEventListener('click', function () {
  const md = document.getElementById('md');
  const start = md.selectionStart;
  const end = md.selectionEnd;
  md.value = md.value.slice(0, start) + '**' + md.value.slice(start, end) + '**' + md.value.slice(end);
  md.focus();
  md.setSelectionRange(start + 2, end + 2);
});
</script>

Best practices

  • Treat selectionEnd as exclusive and pass it straight to slice() or substring().
  • Save selectionStart and selectionEnd before changing the value, because assigning a new value moves the caret to the end.
  • Restore the selection with setSelectionRange() after editing, so the user keeps their place.
  • Guard against null on input types the property doesn't apply to, such as email and number.

Frequently asked questions

What does selectionEnd return in JavaScript?
selectionEnd returns the index just after the last selected character in a text field. For the word Hello selected at the start of a value, it returns 5.
Is selectionEnd inclusive or exclusive?
selectionEnd is exclusive. It points to the position after the selection, which matches how value.slice(start, end) stops before its end index.
Why are selectionStart and selectionEnd the same?
selectionEnd equals selectionStart whenever no text is selected. Both then hold the caret position inside the field.
How do I select all the text in an input with JavaScript?
Call input.select() to select everything in the field. Setting selectionStart to 0 and selectionEnd to input.value.length selects the same text.
How do I put the cursor at the end of an input?
Set selectionStart and selectionEnd to input.value.length, then call focus(). Assigning a new value to an input also moves the caret to the end, as the HTML standard requires.
Why doesn't window.getSelection() return the text selected in a textarea?
window.getSelection() doesn't return text selected inside a textarea in Firefox, according to MDN. Use value.slice(el.selectionStart, el.selectionEnd) instead, which works across browsers.