Navigation API
This lesson explains Navigation API with clear examples, use cases, and best practices so you can use HTML5 APIs confidently in real web applications.
HTML5 Navigation API Overview
The HTML5 Navigation API is a modern browser API designed to
improve client-side navigation in web applications. It provides a
cleaner way to intercept navigation events, manage same-document
navigation, handle page transitions, update content without full
reloads, and build Single Page Application routing.
The Navigation API is commonly used in modern SPAs, documentation
sites, dashboards, admin panels, e-commerce filters, app shells,
page transitions, and web applications that need smooth browser
navigation while keeping URLs meaningful and bookmark-friendly.
| Feature | Description |
| API Name | Navigation API |
| Main Object | window.navigation |
| Main Event | navigate |
| Main Purpose | Handle browser navigation in modern web apps. |
| Related APIs | History API, Location API, URL API, View Transitions API. |
| Best Use | SPA routing, page transitions, app navigation, route
handling. |
Basic Navigation API Example
// HTML5 Navigation API
if ("navigation" in window) {
navigation.addEventListener("navigate", (event) => {
console.log("Navigating to:", event.destination.url);
});
} else {
console.log("Navigation API is not supported.");
}
This example listens for navigation events and logs the
destination URL. Always use feature detection because browser
support may vary.
Navigation API Core Concepts
| Concept | Description | Example |
| Navigation Object | Global object used to inspect and control navigation. | window.navigation |
| Navigate Event | Fires when navigation is about to happen. | navigation.addEventListener("navigate", callback) |
| Destination | Information about where the browser is navigating. | event.destination.url |
| Intercept | Allows app code to handle navigation manually. | event.intercept() |
| Entries | Represents navigation history entries. | navigation.entries() |
| Current Entry | Represents the current navigation entry. | navigation.currentEntry |
Intercept Navigation Example
navigation.addEventListener("navigate", (event) => {
const url =
new URL(event.destination.url);
if (url.origin !== location.origin) {
return;
}
event.intercept(
{
handler: async () => {
const response =
await fetch(url.pathname);
const html =
await response.text();
document.querySelector("#app").innerHTML =
html;
}
}
);
});
This example intercepts same-origin navigation, fetches new
content, and updates the page without a full browser reload.
Handle Same-Origin Navigation Only
navigation.addEventListener("navigate", (event) => {
const url =
new URL(event.destination.url);
if (url.origin !== location.origin) {
return;
}
console.log("Internal app navigation.");
});
In most SPAs, only same-origin navigation should be intercepted.
External links should usually behave like normal browser
navigation.
Navigation API Properties and Methods
| Property / Method | Description | Example Syntax |
navigation.currentEntry | Returns the current navigation entry. | navigation.currentEntry.url |
navigation.entries() | Returns navigation history entries. | navigation.entries() |
navigation.navigate() | Starts navigation programmatically. | navigation.navigate("/about") |
navigation.reload() | Reloads the current navigation entry. | navigation.reload() |
navigation.traverseTo() | Moves to a specific navigation entry. | navigation.traverseTo(key) |
navigation.canGoBack | Checks whether backward navigation is possible. | navigation.canGoBack |
navigation.canGoForward | Checks whether forward navigation is possible. | navigation.canGoForward |
Programmatic Navigation
async function goToPage(path) {
if (!("navigation" in window)) {
location.href = path;
return;
}
await navigation.navigate(path).finished;
}
goToPage("/dashboard");
The navigate() method can be used to start navigation from
JavaScript. A fallback using location.href keeps older
browsers functional.
Simple SPA Router with Navigation API
const routes =
{
"/": "Home Page",
"/about": "About Page",
"/contact": "Contact Page"
};
function render(pathname) {
document.querySelector("#app").textContent =
routes[pathname] || "Page Not Found";
}
if ("navigation" in window) {
navigation.addEventListener("navigate", (event) => {
const url =
new URL(event.destination.url);
if (url.origin !== location.origin) {
return;
}
event.intercept(
{
handler: async () => {
render(url.pathname);
}
}
);
});
}
render(location.pathname);
This example creates a small route map and renders different
content based on the current path.
Navigation with View Transition Example
navigation.addEventListener("navigate", (event) => {
const url =
new URL(event.destination.url);
if (url.origin !== location.origin) {
return;
}
event.intercept(
{
handler: async () => {
if ("startViewTransition" in document) {
await document.startViewTransition(() => {
render(url.pathname);
}).finished;
} else {
render(url.pathname);
}
}
}
);
});
The Navigation API can be combined with the View Transitions API
to create smooth page transitions in app-style websites.
Navigation Events
| Event | Description | Common Use |
navigate | Fires before navigation happens. | Intercept routes and update UI. |
currententrychange | Fires when the current navigation entry changes. | Update active navigation state. |
navigateerror | Fires when navigation fails. | Show error UI or fallback page. |
navigatesuccess | Fires when navigation completes successfully. | Hide loaders and track analytics. |
Show Loading State During Navigation
navigation.addEventListener("navigate", (event) => {
const url =
new URL(event.destination.url);
if (url.origin !== location.origin) {
return;
}
event.intercept(
{
handler: async () => {
document.body.classList.add("is-loading");
try {
await loadPage(url.pathname);
} finally {
document.body.classList.remove("is-loading");
}
}
}
);
});
Loading states help users understand that route content is
changing, especially when fetching remote data.
Update Active Navigation Link
function updateActiveLink() {
document
.querySelectorAll("a[data-nav-link]")
.forEach((link) => {
const isActive =
link.pathname === location.pathname;
link.classList.toggle("active", isActive);
link.setAttribute(
"aria-current",
isActive ? "page" : "false"
);
});
}
navigation.addEventListener(
"currententrychange",
updateActiveLink
);
updateActiveLink();
Updating aria-current="page" improves accessibility by
communicating the current page to assistive technologies.
Browser Support and Fallback
function supportsNavigationApi() {
return "navigation" in window;
}
if (supportsNavigationApi()) {
console.log("Use Navigation API.");
} else {
console.log("Use History API fallback.");
}
Because support can vary, production apps should provide a
fallback using the History API, traditional links, or framework
router behavior.
Navigation API vs History API
| Feature | Navigation API | History API |
| Main Object | window.navigation | window.history |
| Navigation Event | navigate | popstate |
| Intercept Navigation | Built in | Manual link handling needed |
| Modern App Routing | More direct | Widely supported and commonly used |
| Browser Support | Newer and variable | Very broad |
Common Navigation API Use Cases
- Single Page Application routing.
- Client-side page transitions.
- Documentation website navigation.
- Admin dashboard page switching.
- Search and filter result navigation.
- App shell routing for PWAs.
- Unsaved form warning flows.
- Navigation analytics and loading states.
Navigation API Best Practices
-
Use feature detection before accessing
window.navigation.
-
Intercept only same-origin navigation unless you have a clear
reason.
- Keep URLs meaningful, readable, and bookmark-friendly.
-
Provide fallback behavior using the History API or normal links.
-
Update page title, focus, active navigation, and accessibility
state after navigation.
- Show loading and error states for async route changes.
- Do not break browser Back and Forward behavior.
-
Ensure server-side support for deep links in SPA applications.
Common Navigation API Mistakes
-
Using the Navigation API without checking browser support.
- Intercepting external links unnecessarily.
-
Changing content without updating document title or focus.
- Breaking browser Back and Forward behavior.
- Not handling navigation errors.
- Creating routes that cannot be bookmarked or refreshed.
- Ignoring accessibility after route changes.
- Using Navigation API when simple links are enough.
Key Takeaways
-
The Navigation API provides modern browser navigation control.
- Use
window.navigation to access the API. -
Use the
navigate event to detect navigation attempts.
-
Use
event.intercept() for client-side routing.
- Use feature detection and provide History API fallback.
-
Keep navigation accessible, predictable, and bookmark-friendly.
Pro Tip
Use the Navigation API for modern app-style routing, but always
keep normal links working. The best routing systems support
progressive enhancement: links work without JavaScript, and
JavaScript enhances them with smooth transitions, loading states,
and fast client-side rendering.