Iframes and Back Navigation - How to Fix the Browser History Bug

Many of us have worked with iframes in our web development careers. They are everywhere, and while they are usually fairly straightforward to implement, one little quirk is the back navigation bug. Today I was implementing an iframe in a React component and this problem came up. What I'm going to illustrate in this post is going to use ReactJS, however the JS is provided too. My component renders one iframe, and there are buttons in the UI that allow the user to switch the iframe's src url. These src changes were state updates, not navigation, however the iframe src change was adding to the browser history as if my app was navigating and this caused my browser's back button to have a bunch of junk history to go back through. My user went from page A to page B to see the iframe and use the buttons to switch the src for different content, and when they hit the browser back button they expect to go straight back to page A. What was actually happening is that every switch in src was adding not one but two entries to the history so the user would have to click, and click, and click, and what is going on....? What they saw was the iframe changing, not changing, changing, not changing. In short, a mess! Most users would know that this was a back nav through the iframe changes and think "But why is there an extra blank/nothing click in between? And why do we even need those iframe change navigations? I just want to go back to the previous page!" I thought about making a back button on the page that would skip the user directly back to the page they were expecting to see, but that didn't change anything in the history. Eventually they would have to get past that junk unless they completely switch to in-app navigation. That's not ok with me. There has to be a way to fix this right? Read on! With Iframes we have a reference to the contentWindow. The content window is the window object of the document inside the iframe. Window.location can be replaced in history, adding is not required. Can I put these two ideas together and solve my problem? Yes. This worked for me, so please give it a try. First, I added a ref to my iframe with the useRef hook. If you aren't familiar with useRef yet I suggest you check it out, but it is a common way React developers refrain from using the document.getElement methods. I add my ref to my iframe: The code to switch the src is a simple switch statement in a function triggered by the button clicks. Once the newSrcURL value is updated per the switch, the code that will solve this back navigation problem is: iframe.current.contentWindow.location.replace(newSrcURL) When you use the useRef hook, you then access your element with .current. So iframeRef.current above is equal to: document.getElementById('vidFrame') Then we access the contentWindow and use location.replace to replace the location instead of pushing to the history, which adds to the history. The outcome is that your user can go from /page-a to /page-b (with the iframe), switch the src as much as they want, hit the browser back and go straight back to /page-a. Note that my iframe is not directly tied to state anymore. The iframe's jsx has src as 'about:blank.' My iframe is using content from third party servers, btw, in case some of you are thinking that this won't work for you for that reason. Good thinking, but it does work! I am happy to hear your comments and thoughts and let me know if this works for you!

Mar 29, 2025 - 01:29
 0
Iframes and Back Navigation - How to Fix the Browser History Bug

Many of us have worked with iframes in our web development careers. They are everywhere, and while they are usually fairly straightforward to implement, one little quirk is the back navigation bug.

Today I was implementing an iframe in a React component and this problem came up. What I'm going to illustrate in this post is going to use ReactJS, however the JS is provided too.

My component renders one iframe, and there are buttons in the UI that allow the user to switch the iframe's src url. These src changes were state updates, not navigation, however the iframe src change was adding to the browser history as if my app was navigating and this caused my browser's back button to have a bunch of junk history to go back through. My user went from page A to page B to see the iframe and use the buttons to switch the src for different content, and when they hit the browser back button they expect to go straight back to page A. What was actually happening is that every switch in src was adding not one but two entries to the history so the user would have to click, and click, and click, and what is going on....? What they saw was the iframe changing, not changing, changing, not changing. In short, a mess!

Most users would know that this was a back nav through the iframe changes and think "But why is there an extra blank/nothing click in between? And why do we even need those iframe change navigations? I just want to go back to the previous page!"

I thought about making a back button on the page that would skip the user directly back to the page they were expecting to see, but that didn't change anything in the history. Eventually they would have to get past that junk unless they completely switch to in-app navigation. That's not ok with me. There has to be a way to fix this right? Read on!

With Iframes we have a reference to the contentWindow. The content window is the window object of the document inside the iframe. Window.location can be replaced in history, adding is not required. Can I put these two ideas together and solve my problem? Yes. This worked for me, so please give it a try.

First, I added a ref to my iframe with the useRef hook. If you aren't familiar with useRef yet I suggest you check it out, but it is a common way React developers refrain from using the document.getElement methods. I add my ref to my iframe:

              

The code to switch the src is a simple switch statement in a function triggered by the button clicks. Once the newSrcURL value is updated per the switch, the code that will solve this back navigation problem is:

iframe.current.contentWindow.location.replace(newSrcURL)

When you use the useRef hook, you then access your element with .current. So iframeRef.current above is equal to:

document.getElementById('vidFrame')

Then we access the contentWindow and use location.replace to replace the location instead of pushing to the history, which adds to the history.

The outcome is that your user can go from /page-a to /page-b (with the iframe), switch the src as much as they want, hit the browser back and go straight back to /page-a. Note that my iframe is not directly tied to state anymore. The iframe's jsx has src as 'about:blank.'

My iframe is using content from third party servers, btw, in case some of you are thinking that this won't work for you for that reason. Good thinking, but it does work!

I am happy to hear your comments and thoughts and let me know if this works for you!