Advance JavaScript (DOM, BOM, Web API) / Web API

History

πŸ•˜ History API

The History API allows JavaScript to control the browser's navigation history.

It is essential for building Single Page Applications (SPAs) where URLs change without reloading the page.


πŸ“Œ What Is the History API?

The browser maintains a history stack, like a list of visited pages.

[ Page1 ] β†’ [ Page2 ] β†’ [ Page3 ] β†’ ...

The History API lets you:

  • Move through this stack (back(), forward(), go())

  • Add or modify history entries (pushState(), replaceState())

  • React to user navigation (popstate event)



πŸ‘€ Basic History API Methods

πŸ“Œ 1 history.length

Shows how many entries exist in the session history.

console.log(history.length);

πŸ“Œ 2 history.back()

Same as pressing browser Back button.

history.back();

πŸ“Œ 3 history.forward()

Moves forward in the stack if possible.

history.forward();

πŸ“Œ 4 history.go(n)

history.go(-2); // Go 2 pages back
history.go(1);  // Go forward

🧠 Manipulating Browser History Without Page Reload

Normally, when you change a URL:

/home β†’ /profile

πŸ‘‰ The browser reloads the page

πŸ‘‰ HTML, CSS, JS are downloaded again

πŸ‘‰ State is lost

πŸ“Œ Traditional Navigation (Reload Happens)

<a href="/profile">Profile</a>
Click link
β†’ Browser requests /profile
β†’ Page reload
β†’ JS starts again

πŸ“Œ What History API Changes

The History API allows you to:

Change the URL AND browser history WITHOUT reloading the page

This is the foundation of SPAs (React, Angular, Vue, Next.js).

πŸ“Œ Core Idea (Very Important)

URL β‰  Page Reload

With History API:

  • URL can change

  • History stack can update

  • UI updates manually using JS

  • Browser back/forward still works


πŸ“Œ The Two Main Methods

1️⃣ history.pushState()

2️⃣ history.replaceState()

πŸ“Œ 1. history.pushState() β€” Add New History Entry

history.pushState(stateObject, title, url);

Parameters Explained

Parameter

Meaning

stateObject

JS data saved with this history entry

title

Ignored by most browsers

url

New URL shown in address bar

βœ” URL changes to /profile

βœ” Page does NOT reload

βœ” New history entry is added

You MUST Update UI Manually

history.pushState({ page: "profile" }, "", "/profile");
renderProfilePage();

History API:

  • Changes URL

  • Changes history

  • DOES NOT change UI automatically


πŸ“Œ 2. history.replaceState() β€” Replace Current Entry

βœ” URL changes

βœ” No new history entry

βœ” Back button skips Login

When to Use replaceState()

Use Case

Why

Login redirect

Prevent going back to login

Fix wrong URL

Update without history pollution

Step-based forms

Replace instead of pushing


πŸ“Œ popstate Event β€” Reacting to History Navigation

Triggered when user clicks Back or Forward, NOT when calling pushState/replaceState.

When popstate Fires

Action

popstate

Browser Back button

βœ…

Browser Forward button

βœ…

history.go(-1)

βœ…

history.go(1)

βœ…

history.pushState()

❌

history.replaceState()

❌


❓ When to Use History API

When

Why

Building SPA

Avoids full page reload

Custom navigation

You control URL + UI

Dynamic content

Helps maintain browser navigation behavior

Scroll restoration

Remember user’s scroll position


❗️ Limitations

  • Cannot navigate to external websites using pushState.

  • state object should be small.

  • Does not trigger popstate when using pushState() or replaceState().


🧩 History API – Example

πŸ“ Project Structure

history-api-demo/
β”‚
β”œβ”€β”€ index.html
β”œβ”€β”€ style.css
└── script.js
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>History API Demo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link rel="stylesheet" href="style.css" />
</head>

<body>

  <!-- Navigation -->
  <nav>
    <button id="home">Home</button>
    <button id="profile">Profile</button>
    <button id="about">About</button>
  </nav>

  <!-- Content Area -->
  <main id="content">
    <h1>Home Page</h1>
    <p>Welcome! Click the buttons above to navigate.</p>
  </main>

  <footer>
    Try using browser Back & Forward buttons
  </footer>

  <script src="script.js"></script>
</body>
</html>
/* ===== RESET ===== */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: Arial, Helvetica, sans-serif;
}

body {
  background: #f4f6f8;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* ===== NAVBAR ===== */
nav {
  width: 100%;
  background: #1e293b;
  padding: 16px;
  display: flex;
  justify-content: center;
  gap: 20px;
}

nav button {
  background: #334155;
  color: white;
  border: none;
  padding: 10px 18px;
  font-size: 16px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.2s ease;
}

nav button:hover {
  background: #475569;
}

/* ===== CONTENT ===== */
#content {
  margin-top: 60px;
  padding: 40px;
  background: white;
  width: 90%;
  max-width: 600px;
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.1);
  text-align: center;
}

#content h1 {
  font-size: 36px;
  margin-bottom: 16px;
  color: #0f172a;
}

#content p {
  font-size: 18px;
  color: #475569;
}

/* ===== FOOTER ===== */
footer {
  margin-top: 30px;
  font-size: 14px;
  color: #64748b;
}
const content = document.getElementById("content");

function render(page) {
  content.innerHTML = `
    <h1>${page} Page</h1>
    <p>This content was loaded without page refresh.</p>
  `;
}

function navigate(page, url) {
  history.pushState({ page }, "", url);
  render(page);
}

// Navigation buttons
document.getElementById("home").addEventListener("click", () => {
  navigate("Home", "/home");
});

document.getElementById("profile").addEventListener("click", () => {
  navigate("Profile", "/profile");
});

document.getElementById("about").addEventListener("click", () => {
  navigate("About", "/about");
});

// Handle browser Back & Forward buttons
window.addEventListener("popstate", (event) => {
  if (event.state) {
    render(event.state.page);
  } else {
    render("Home");
  }
});

🧠 How This Example Works

πŸ”Ή Clicking a button

Button Click
β†’ pushState()
β†’ URL changes
β†’ render() updates content
β†’ NO PAGE RELOAD

πŸ”Ή Pressing Back / Forward

Browser navigation
β†’ popstate event fires
β†’ event.state contains page info
β†’ UI updates accordingly

πŸ§ͺ What You Should Test

  1. Click Profile β†’ URL becomes /profile

  2. Click About β†’ URL becomes /about

  3. Press Back β†’ Goes to Profile

  4. Press Forward β†’ Goes to About

  5. Refresh page β†’ stays on last URL