👀 Live Preview
Click a tab — the hash updates and content changes without reload:
Current hash: (none)

The onhashchange handler runs JavaScript when the URL hash (fragment identifier) changes — the part after # in the address bar. Unlike onfocus on form fields, this is a window-level event: you assign window.onhashchange or use window.addEventListener("hashchange", …). It fires when users click in-page anchor links, use back/forward on hash URLs, or when script sets location.hash. Common uses include simple tab panels, lightweight “single-page” views, and deep links to a section — all without reloading the page.
Not on inputs.
# fragment.
Read the hash.
Swap content.
Preferred way.
History API.
onhashchange AttributeThe primary purpose of onhashchange is to react when the hash portion of the URL changes so your page can update content without a full reload. For example, clicking <a href="#about"> changes the hash to #about; your handler reads location.hash and shows the About panel.
Hash routing is a beginner-friendly pattern for small apps and tutorials. Larger production apps often use the History API (pushState + popstate) instead, but understanding hashchange is still valuable — many sites and docs use hash links.
hashchange does not fire on initial page load. Call your render function once after attaching the handler so the first URL (e.g. #home) displays correctly.
Assign the handler on window — the event target for hash changes:
<script>
function handleHashChange() {
const hash = location.hash.slice(1) || "home";
document.getElementById("content").textContent = "View: " + hash;
}
window.onhashchange = handleHashChange;
handleHashChange(); // initial render
</script>window, not individual HTML elements.hashchange event fires.location.hash = "#foo", and browser back/forward on hash URLs.?id=1) or path changes without a hash change.window.onhashchange = function() { … }.window.addEventListener("hashchange", handler).The onhashchange property accepts a function (or function reference):
window.onhashchange = handleHashChange — Named function reference.window.onhashchange = function() { … } — Inline anonymous function.window.addEventListener("hashchange", handler).window.addEventListener("hashchange", () => {
const section = location.hash.slice(1) || "home";
console.log("Hash is now:", section);
renderSection(section);
});
// Also run on first load:
renderSection(location.hash.slice(1) || "home");| Action | hashchange fires? | Notes |
|---|---|---|
Click <a href="#about"> | Yes | Classic in-page nav |
location.hash = "#settings" | Yes | Programmatic change |
| Browser Back on hash history | Yes | History entry with different hash |
First page load with #home | No | Call render manually once |
Change query only (?page=2) | No | Hash unchanged |
history.pushState() (path only) | No | Use popstate instead |
| Target | Supported? | Notes |
|---|---|---|
window | Yes | Primary and correct target |
document / window.addEventListener | Yes | Recommended registration |
<input>, <button> | No | Not a form/element event |
<body onhashchange> | Avoid | Use window in script instead |
hashchange vs popstate vs onfocus| Handler / event | When it fires | Typical use |
|---|---|---|
hashchange | location.hash changes | Simple tabs, hash routing |
popstate | History navigation (pushState entries) | Modern SPA routing |
onfocus | Element gains focus | Form fields, keyboard UX |
Swap content from the URL hash, register with addEventListener, and handle the initial load.
Click a tab — the hash updates and content changes without reload:
Current hash: (none)
Update a content region whenever the URL fragment changes:
<h1>Dynamic Content Based on Hash</h1>
<nav>
<a href="#home">Home</a>
<a href="#about">About</a>
</nav>
<div id="content"></div>
<script>
function handleHashChange() {
var hash = location.hash.substring(1) || "home";
document.getElementById("content").textContent =
"Content based on hash: " + hash;
}
window.onhashchange = handleHashChange;
handleHashChange();
</script>The browser fires hashchange on window when the fragment changes. Reading location.hash tells you which “view” to show.
Attach the handler with addEventListener:
<script>
window.addEventListener("hashchange", function () {
console.log("Hash changed to:", location.hash);
});
// Or property form:
window.onhashchange = function () { /* … */ };
</script>Register once at page load. Any hash change — from links or script — triggers the same callback.
Because hashchange does not fire on first load, call your render function immediately:
function renderFromHash() {
const id = location.hash.slice(1) || "home";
document.querySelectorAll("[data-view]").forEach(el => {
el.hidden = el.dataset.view !== id;
});
}
window.addEventListener("hashchange", renderFromHash);
renderFromHash(); // run once for URL like page.html#aboutShare one function between the event listener and the initial call — keeps first paint and later navigation consistent.
document.title so screen reader users know the page context changed.tabindex="-1" if appropriate.<h1> or <h2> for structure.aria-live regions when dynamic panels update.Link click or script.
Same document stays.
onhashchange runs.
Tabs, panels, deep links.
The hashchange event and window.onhashchange are supported in all modern browsers — Chrome, Firefox, Safari, and Edge. Internet Explorer 8+ also supports it.
hashchange supportAll major browsers fire the event on the window object when the URL fragment changes.
Bottom line: Safe for hash-based navigation in all browsers you are likely to support today.
addEventListener("hashchange", …) in production code#settings)document.title when the main view changesonhashchange to form elements — use windowhashchange fires on first loadThe onhashchange handler lets your page respond when the URL fragment changes — a simple way to build tabs, lightweight routing, and shareable deep links without reloading.
Register on window, read location.hash, run your render logic once on load, and prefer addEventListener for maintainable code.
onhashchangeBookmark these before building hash-based navigation.
Not on inputs.
ScopeFragment ID.
URLSame document.
SPARender manually.
GotchaHistory API.
Compare#fragment) changes — on the window object, not on form elements.window.onhashchange or window.addEventListener("hashchange", handler).hashchange tracks location.hash. popstate tracks History API navigation from pushState / replaceState.addEventListener("hashchange", handler) is preferred for production. window.onhashchange is fine for learning.Practice the onhashchange handler with tab-style examples in the Try It editor.
5 people found this page helpful