Start · Sprachen · JavaScript · Referenz · HTMLInputElement.setSelectionRange()

HTMLInputElement.setSelectionRange()

Methode

Legt Start- und Endposition der Textauswahl bzw. die Cursorposition in einem <code>&lt;input&gt;</code>- oder <code>&lt;textarea&gt;</code>-Element fest.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

HTMLInputElement.prototype.setSelectionRange(selectionStart, selectionEnd, selectionDirection)

Beschreibung

setSelectionRange() markiert einen Textbereich in einem Eingabefeld oder setzt den Cursor an eine bestimmte Stelle. Die Positionen sind nullbasierte Zeichen-Indizes (UTF-16-Codeeinheiten). Sind Start und Ende gleich, wird keine Auswahl erzeugt, sondern nur der Cursor (Caret) an diese Stelle gesetzt.

Typische Einsatzfälle sind: den Cursor nach dem programmatischen Ändern von value an die richtige Stelle zurücksetzen (z. B. bei Eingabemasken für Telefonnummern oder IBANs), einen Teil des Inhalts vorauswählen (etwa den Dateinamen ohne Endung beim Umbenennen) oder Autovervollständigung, bei der der ergänzte Teil markiert bleibt und durch Weitertippen überschrieben wird.

Die Methode ist auch auf HTMLTextAreaElement verfügbar. Bei <input> funktioniert sie nur mit den Typen text, search, url, tel und password. Für andere Typen (z. B. email, number, date) wird eine InvalidStateError-DOMException geworfen.

Damit die Auswahl sichtbar wird, muss das Element in der Regel fokussiert sein — rufe also vorher focus() auf. Die aktuelle Auswahl kann über selectionStart, selectionEnd und selectionDirection ausgelesen werden.

Parameter

Name Typ Default Beschreibung
$selectionStart Pflicht number | null Index des ersten ausgewählten Zeichens (nullbasiert). Werte größer als die Textlänge werden auf die Länge begrenzt. null wird wie 0 behandelt.
$selectionEnd Pflicht number | null Index hinter dem letzten ausgewählten Zeichen. Werte größer als die Textlänge werden auf die Länge begrenzt. Ist selectionEnd kleiner als selectionStart, werden beide auf selectionEnd gesetzt.
$selectionDirection "forward" | "backward" | "none" "none" Richtung der Auswahl, also an welchem Ende der Cursor steht. Auf Systemen ohne Richtungskonzept (z. B. macOS teils) wird "none" wie "forward" behandelt.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Löst ggf. ein select-Event bzw. selectionchange am Element aus.

Beispiele

Dateinamen ohne Endung vorauswählen

// <input id="filename" type="text" value="urlaubsfoto.jpg">
const input = document.querySelector('#filename');
input.focus();

const dot = input.value.lastIndexOf('.');
const end = dot > 0 ? dot : input.value.length;
input.setSelectionRange(0, end);

console.log(input.value.slice(input.selectionStart, input.selectionEnd));
urlaubsfoto

Cursor ans Ende setzen

// <textarea id="notiz">Erste Zeile\nZweite Zeile</textarea>
const area = document.querySelector('#notiz');
area.focus();
const len = area.value.length;
// Start = Ende → keine Auswahl, nur Cursorposition
area.setSelectionRange(len, len);
console.log(area.selectionStart, area.selectionEnd);
24 24

Eingabemaske: Cursorposition nach Formatierung erhalten

// <input id="iban" type="text">
const iban = document.querySelector('#iban');

iban.addEventListener('input', () => {
  const pos = iban.selectionStart;
  // Anzahl Nicht-Leerzeichen vor dem Cursor merken
  const rawBefore = iban.value.slice(0, pos).replace(/\s/g, '').length;

  const raw = iban.value.replace(/\s/g, '').toUpperCase();
  iban.value = raw.replace(/(.{4})/g, '$1 ').trim();

  // Neue Cursorposition berechnen (je 4 Zeichen ein Leerzeichen)
  let newPos = rawBefore + Math.floor(rawBefore / 4);
  if (rawBefore > 0 && rawBefore % 4 === 0) newPos -= 1;
  iban.setSelectionRange(newPos, newPos);
});

Autovervollständigung mit markiertem Vorschlag

// <input id="stadt" type="search">
const staedte = ['Berlin', 'Bremen', 'Hamburg', 'München'];
const feld = document.querySelector('#stadt');

feld.addEventListener('input', (e) => {
  if (e.inputType?.startsWith('delete')) return;
  const getippt = feld.value;
  const treffer = staedte.find((s) => s.toLowerCase().startsWith(getippt.toLowerCase()));
  if (treffer && getippt) {
    feld.value = getippt + treffer.slice(getippt.length);
    // Ergänzten Teil markieren – Weitertippen überschreibt ihn
    feld.setSelectionRange(getippt.length, treffer.length, 'backward');
  }
});

// Wichtig · Fallstricke

  • Nicht unterstützte Input-Typen: Bei type="email", number, date, color usw. wirft der Aufruf eine InvalidStateError-DOMException. Wer eine Auswahl in E-Mail-Feldern braucht, muss notfalls auf type="text" mit inputmode="email" ausweichen. Vor dem Aufruf lässt sich mit try…catch oder einer Prüfung von selectionStart !== null absichern.
  • Fokus: Ohne Fokus wird die Auswahl zwar gespeichert, aber meist nicht angezeigt. Einige ältere Browser verschieben beim Aufruf den Fokus ungefragt. Auf iOS wirkt die Methode oft nur, wenn sie direkt in einer Nutzeraktion (z. B. click, focus) aufgerufen wird.
  • Zeitpunkt beim Fokussieren: Im focus-Handler setzt der Browser die Cursorposition bei Mausklick danach erneut. Den Aufruf daher ggf. mit requestAnimationFrame() oder setTimeout(…, 0) verzögern.
  • Indizes sind UTF-16-Codeeinheiten: Emojis und andere Zeichen außerhalb der BMP zählen als 2. Wer mit [...str].length rechnet, erhält abweichende Positionen.
  • Zeilenumbrüche in <textarea>: value normalisiert Umbrüche auf \n; die Indizes beziehen sich auf diesen normalisierten Wert.
  • Zum Ersetzen des markierten Texts eignet sich setRangeText() besser als manuelles String-Zusammenbauen, da dabei die Auswahl kontrolliert angepasst wird.