Start · Sprachen · JavaScript · Referenz · Location.hash

Location.hash

Eigenschaft

Liest oder setzt den Fragment-Teil der aktuellen URL – ein <code>#</code> gefolgt vom Fragment-Bezeichner, z. B. <code>#kapitel-2</code>.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

Location.hash

Beschreibung

Die Eigenschaft location.hash enthält den Fragment-Bezeichner der aktuellen Dokument-URL einschließlich des führenden #. Hat die URL kein Fragment oder nur ein leeres (https://example.com/#), ist der Wert eine leere Zeichenkette "".

Die Eigenschaft lässt sich auch schreiben. Beim Setzen wird das Fragment geändert, ohne dass die Seite neu geladen wird. Der Browser scrollt zum Element mit passender id (bzw. einem <a name>), legt einen neuen Eintrag im Verlauf an und löst das Ereignis hashchange auf window aus. Das führende # kannst du beim Setzen weglassen – der Browser ergänzt es.

Typische Einsatzzwecke sind Sprungmarken innerhalb langer Seiten, das Speichern einfacher Zustände in der URL (z. B. aktiver Tab), sowie einfache hashbasierte Router in Single-Page-Anwendungen. Für Routing ohne # ist die History-API heute meist die bessere Wahl.

Wichtig: Der Fragment-Teil wird nie an den Server gesendet. Er existiert nur im Browser und ist deshalb serverseitig nicht auswertbar.

Parameter

Name Typ Default Beschreibung
$wert string Nur beim Setzen: Neues Fragment, mit oder ohne führendes #. Sonderzeichen werden prozentkodiert.

Rückgabewert

Typ
string
Beschreibung
Das Fragment inklusive # (z. B. "#faq") oder "", wenn kein bzw. ein leeres Fragment vorhanden ist. Der Wert ist prozentkodiert.

Beispiele

Fragment auslesen und dekodieren

// URL: https://example.com/doku#%C3%9Cbersicht
const roh = location.hash;            // "#%C3%9Cbersicht"
const fragment = decodeURIComponent(roh.slice(1));
console.log(roh);
console.log(fragment);
#%C3%9Cbersicht Übersicht

Aktiven Tab in der URL merken

const tabs = document.querySelectorAll('[role="tab"]');

const aktiviereTab = (id) => {
  tabs.forEach((tab) => {
    tab.setAttribute('aria-selected', String(tab.dataset.tab === id));
  });
};

tabs.forEach((tab) => {
  tab.addEventListener('click', () => {
    location.hash = tab.dataset.tab; // '#' wird automatisch ergänzt
  });
});

// Beim Laden und bei Zurück/Vor den Zustand wiederherstellen
const sync = () => aktiviereTab(location.hash.slice(1) || 'allgemein');
window.addEventListener('hashchange', sync);
sync();

Minimaler Hash-Router

const routen = {
  '': () => '<h1>Startseite</h1>',
  '#/kontakt': () => '<h1>Kontakt</h1>',
  '#/impressum': () => '<h1>Impressum</h1>'
};

const render = () => {
  const ansicht = routen[location.hash] ?? (() => '<h1>404 – nicht gefunden</h1>');
  document.querySelector('#app').textContent = '';
  document.querySelector('#app').insertAdjacentHTML('beforeend', ansicht());
};

window.addEventListener('hashchange', render);
window.addEventListener('DOMContentLoaded', render);

Fragment entfernen ohne Neuladen und ohne Verlaufseintrag

// location.hash = '' lässt ein '#' in der URL stehen
// Sauber entfernen mit der History-API:
const entferneHash = () => {
  history.replaceState(null, '', location.pathname + location.search);
};

console.log(location.href); // https://example.com/seite?x=1#abschnitt
entferneHash();
console.log(location.href);
https://example.com/seite?x=1#abschnitt https://example.com/seite?x=1

// Wichtig · Fallstricke

  • Kodierung: Der Rückgabewert ist prozentkodiert. Vor der Anzeige oder dem Vergleich mit decodeURIComponent() dekodieren (ggf. in try/catch, da fehlerhafte Sequenzen einen URIError werfen).
  • Leeres Fragment: https://example.com/# und https://example.com/ liefern beide "". Setzt man location.hash = "", bleibt ein # in der URL stehen – zum vollständigen Entfernen history.replaceState() nutzen.
  • Verlauf & Scrollen: Jede Zuweisung erzeugt einen neuen Verlaufseintrag und scrollt zum Ziel-Element. Wer beides vermeiden will, verwendet history.replaceState() – das löst allerdings kein hashchange aus.
  • Gleicher Wert: Wird derselbe Hash erneut gesetzt, feuert kein hashchange.
  • Sicherheit (XSS): Der Hash ist vollständig vom Nutzer bzw. Angreifer kontrollierbar (DOM-basiertes XSS). Niemals ungeprüft in innerHTML, document.write(), eval() oder als Selektor in querySelector() verwenden – für Selektoren CSS.escape() oder besser document.getElementById() einsetzen. Da der Hash nicht an den Server gesendet wird, taucht er in Server-Logs nicht auf und wird von serverseitigen Filtern nicht erfasst.
  • Kompatibilität: Wird von allen Browsern unterstützt. Für beliebige URLs (nicht nur die aktuelle) bietet URL.prototype.hash dieselbe Funktionalität.