Skip to content

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.

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.

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.

Prevent Unsaved Form Navigation

let hasUnsavedChanges = false;

document
  .querySelector("form")
  .addEventListener("input", () => {
    hasUnsavedChanges = true;
  });

navigation.addEventListener("navigate", (event) => {
  if (!hasUnsavedChanges) {
    return;
  }

  const confirmLeave =
    confirm("You have unsaved changes. Leave this page?");

  if (!confirmLeave) {
    event.preventDefault();
  }
});

Navigation events can be used to warn users before they leave a page with unsaved work.

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.

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.