239

I am doing an online quiz application in PHP. I want to restrict the user from going back in an exam.

I have tried the following script, but it stops my timer.

What should I do?

The timer is stored in file cdtimer.js.

<script type="text/javascript">
    window.history.forward();
    function noBack()
    {
        window.history.forward();
    }
</script>

<body onLoad="noBack();" onpageshow="if (event.persisted) noBack();" onUnload="">

I have the exam timer which takes a duration for the exam from a MySQL value. The timer starts accordingly, but it stops when I put the code in for disabling the back button. What is my problem?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sawant Akshay
  • 2,654
  • 3
  • 14
  • 15
  • [for nodeJS detect and stop back button event of browser](https://stackoverflow.com/a/60740208/10156778) – Darshan Dixit Mar 18 '20 at 13:12
  • This approach will cause blinking - browser will actually navigate back and then go back. You can try my new NPM package to avoid this: https://www.npmjs.com/package/use-history-back-trap) – RandomX Nov 11 '22 at 15:00

40 Answers40

197

There are numerous reasons why disabling the back button will not really work. Your best bet is to warn the user:

window.onbeforeunload = function() { return "Your work will be lost."; };

This page does list a number of ways you could try to disable the back button, but none are guaranteed:

http://www.irt.org/script/311.htm

Jerod Houghtelling
  • 4,783
  • 1
  • 22
  • 30
ColinE
  • 68,894
  • 15
  • 164
  • 232
  • You should check in your PHP code if the answer has been submitted already and if so reject it. – Sela Yair Jun 19 '15 at 14:56
  • 8
    It's worth mentioning that things have now changed in modern browsers: see http://stackoverflow.com/questions/19926641/how-to-disable-back-button-in-browser-using-javascript – devrobf Jun 10 '16 at 12:25
  • it works but, This shows the alert on all the menu buttons as well. when it is going to change page, it shows the alert. Can we just fix it to the back button only – Muhammad Baber Zaman Oct 14 '20 at 12:20
163

It is generally a bad idea overriding the default behavior of the web browser. A client-side script does not have the sufficient privilege to do this for security reasons.

There are a few similar questions asked as well,

You can-not actually disable the browser back button. However, you can do magic using your logic to prevent the user from navigating back which will create an impression like it is disabled. Here is how - check out the following snippet.

(function (global) {

    if(typeof (global) === "undefined") {
        throw new Error("window is undefined");
    }

    var _hash = "!";
    var noBackPlease = function () {
        global.location.href += "#";

        // Making sure we have the fruit available for juice (^__^)
        global.setTimeout(function () {
            global.location.href += "!";
        }, 50);
    };

    global.onhashchange = function () {
        if (global.location.hash !== _hash) {
            global.location.hash = _hash;
        }
    };

    global.onload = function () {
        noBackPlease();

        // Disables backspace on page except on input fields and textarea..
        document.body.onkeydown = function (e) {
            var elm = e.target.nodeName.toLowerCase();
            if (e.which === 8 && (elm !== 'input' && elm  !== 'textarea')) {
                e.preventDefault();
            }
            // Stopping the event bubbling up the DOM tree...
            e.stopPropagation();
        };
    }
})(window);

This is in pure JavaScript, so it would work in most of the browsers. It would also disable the backspace key, but that key will work normally inside input fields and textarea.

Recommended Setup:

Place this snippet in a separate script and include it on a page where you want this behavior. In the current setup it will execute the onload event of the DOM which is the ideal entry point for this code.

Working DEMO!

It was tested and verified in the following browsers,

  • Chrome.
  • Firefox.
  • Internet Explorer (8-11) and Edge.
  • Safari.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rohit416
  • 3,416
  • 3
  • 24
  • 41
  • 1
    I don't understand why the setTimeout. If I just initially append #! to location and remove the setTimeout, it still work. – baraber May 26 '15 at 19:54
  • yes true, it will work, but i if i have to recall something from memory when i had this at first place...the flow was not working properly in chrome as in other browsers. Chrome returned the empty `location.hash` initially so it made me to do it like this. There could be more improvement to this but 50 ms just once didn't cost me much so i leave it there. – Rohit416 May 27 '15 at 06:01
  • Oh, that was a memory challenge, thank you :) I used your solution, but replaced the setInterval by the .onhashchange handler. Works perfectly. But I have another question though : Why do "if (global.location.hash != _hash)" ? I think this condition can only be true all the time because window.location.hash should always return the hash with the '#' character and _hash will never contains the '#' caracter. Do you recall anything on that ? Is that just a protection in case the browser does not return the '#' char in location.hash ? – baraber May 27 '15 at 12:47
  • I created a .js file as recommended and included the js file in my code using the following: But I can still perform a back (using Safari). What am I missing? This library was added in the same fashion as other libraries I use, so the include is good. – Tim May 13 '17 at 11:42
  • The code has been tested in all mentioned browsers and last time when I checked it was working in all. I tested this today in Safari and it was working. Can you just open the working demo link in Safari and see if it works at your end? – Rohit416 May 15 '17 at 07:24
  • 1
    Blocks back button on ipad air, ios 8 – plugincontainer Jan 09 '18 at 17:42
  • without the backspace keyDown handler works on old browser as well but on modern browser I would use JonBrave's solution. I have combined both in my case. – Miklos Krivan Jul 07 '18 at 16:09
  • Warning: This also blocks any click on the main menu button in Waterfox and the Firefox burger menu as well! – Andreas Jul 23 '20 at 05:03
  • @Andreas - As far as Waterfox is concerned, I'm afraid that this solution was never get tested in that browser, the only browsers it has been tested years ago are mentioned in the summary. For the Firefox menu, I can't say as I tested it in my Firefox and it worked, it's not a bullet-proof solution anyway, also, if it would block any handler from executing then a `keydown` or a `keypress` handler is my best bet, so I doubt that if It'd block any `click` event handler. – Rohit416 Jul 23 '20 at 12:06
  • @PaulMcBurney The definition of "no longer works" is a vague statement as it does not state the environment it has been put into for the test, it doesn't mean that environment has to favorable. Besides that, the [Working Demo](http://output.jsbin.com/yaqaho) in the post is the evidence of its health, I tested in Chrome, Firefox, Edge (all latest versions) and IE-11, and **it is working.** I would recommend try clicking on the working demo link and hit the back button (let the page to fully load) and then test! – Rohit416 Jul 29 '20 at 09:35
  • @rohit416. Just tested. The demo is: - Not working with google 87.0.4280.66 - Not working with edge 87.0.664.47 - Still working with ff 83.0. On the two first ones, it works only if the user takes an action on the page (like a click) before deciding to hit the back button. If the user take no action, the script does not work. – Jeremie Nov 26 '20 at 13:03
  • Works on Chrome 87.0.4280.141 on Desktop, but not on Android. – formicini Jan 12 '21 at 08:27
160

I came across this, needing a solution which worked correctly and "nicely" on a variety of browsers, including Mobile Safari (iOS 9 at time of posting). None of the solutions were quite right. I offer the following (tested on Internet Explorer 11, Firefox, Chrome, and Safari):

history.pushState(null, document.title, location.href);
window.addEventListener('popstate', function (event)
{
  history.pushState(null, document.title, location.href);
});

Note the following:

  • history.forward() (my old solution) does not work on Mobile Safari --- it seems to do nothing (i.e., the user can still go back). history.pushState() does work on all of them.
  • the third argument to history.pushState() is a url. Solutions which pass a string like 'no-back-button' or 'pagename' seem to work OK, until you then try a Refresh/Reload on the page, at which point a "Page not found" error is generated when the browser tries to locate a page with that as its URL. (The browser is also likely to include that string in the address bar when on the page, which is ugly.) location.href should be used for the URL.
  • the second argument to history.pushState() is a title. Looking around the web most places say it is "not used", and all the solutions here pass null for that. However, in Mobile Safari at least, that puts the page's URL into the history dropdown the user can access. But when it adds an entry for a page visit normally, it puts in its title, which is preferable. So passing document.title for that results in the same behaviour.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JonBrave
  • 4,045
  • 3
  • 38
  • 115
  • 4
    This is the correct answer. Works perfectly on Chrome, IE 11, Firefox and Edge. – Concept211 Apr 19 '17 at 19:35
  • 4
    This should be the accepted answer, it's cross platform and just works fine. – calbertts Jun 01 '17 at 15:23
  • in jsp sevlet After submit I refresh the page. page not display(error) – Madhuka Dilhan Aug 09 '17 at 07:09
  • Best solution so far, but is probably not working in older browsers – j4n7 Aug 22 '17 at 13:29
  • 3
    Perfect solution for modern browsers. I have combined with @Rohit416 answer to support older browser just using condition typeof (history.pushState) === "function" work smooth. – Miklos Krivan Jul 07 '18 at 16:07
  • Chrome on Mac - walked right through this (hold down the back arrow and full history is there - choose what you like...... :( – Apps-n-Add-Ons Aug 15 '18 at 12:23
  • This does prevent the user from going back but for some reason it also breaks my menu navigation, until I manually refresh the page. – Vincent Jul 05 '19 at 21:48
  • 5
    In Chrome 79.0.3945.130 this isn't working for me. I implemented exactly as above and I'm able to go back by clicking the Back button. When I **hold** the Back button and select any item in the history, it's true that I'm blocked. But a quick click on the Back button takes me right back to the previous page. – gene b. Jan 27 '20 at 16:53
  • 1
    After Version 75 Chrome has changed this behavior, see: https://support.google.com/chrome/thread/8721521?hl=en – gene b. Jan 27 '20 at 17:00
  • How do I undo this once I need to get the back button back? – Boris Verkhovskiy Feb 06 '20 at 17:18
  • @Boris See e.g. https://www.w3schools.com/jsref/met_element_removeeventlistener.asp which I think says you must have added it via "an external function" rather than an "anonymous" one, so change the `addEventListener` call. – JonBrave Feb 07 '20 at 19:06
  • Where should I put this? I put it in document.ready and it does not work – Pedro Joaquín Jul 23 '20 at 19:18
  • 2
    This solution does not work in Chrome. Works in other browsers. I don't know why it no longer works in Chrome. It is a dubious practice, which leads me to believe Chrome is trying to nullify code like this. – Jeff Wilkerson Sep 28 '20 at 21:51
  • Works really well for me thank you! For Chrome it wasn't necessary since the browser behaved as intended but the other ones didn't due to some issue with PHP sessions and post data. I like how it's done in just a few lines!! – Numabyte Feb 26 '21 at 03:58
  • I would improve this a bit, like adding some notifcation to user why button back does not work. Like showing a notification in setTImout within popstate handler. In my case it was like "Navigation backwards after sign ups and purchases is disabled. Please use top site navigation instead" in a toast notification. – Kote Isaev Jan 14 '22 at 03:00
  • 3
    Doesn't work on Chrome 99 untill I click inside the page(probably activates window.focus()). Works fine on Firefox though. Does anyone have any solution for this ? – HarsiddhDave Apr 01 '22 at 06:34
81
<script>
    window.location.hash = "no-back-button";

    // Again because Google Chrome doesn't insert
    // the first hash into the history
    window.location.hash = "Again-No-back-button"; 

    window.onhashchange = function(){
        window.location.hash = "no-back-button";
    }
</script>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
vrfvr
  • 835
  • 6
  • 2
  • 4
    Genius! I used this to prevent accidental trigger of Back button when user hits Backspace (on disabled/readonly fields, for example) in a web app where back/forward didn't really make sense anyway. Confirmed disables back and forward functionality (tho not the buttons themselves), including context menu option; verified in IE8 thru IE11, Chrome & FF. – nothingisnecessary Jan 29 '15 at 19:42
  • 2
    This works, but resets all data entered in textboxes. Is it possible to prevent clearing? – Somnium May 06 '15 at 08:46
  • 7
    It worked for me on firefox, but not on chrome (version 36.0.1985.143) – baraber May 26 '15 at 18:34
  • This worked for me also, but on Firefox it seems to break the `window.history.back()` function. We want to prevent the users clicking on the browser back button, but in some cases we provide our own back button on the page. Is there any way to make it work? – AsGoodAsItGets May 03 '16 at 15:53
  • This worked for me.. I replaced no-back-button with hash of page i want to stay in – Abhishek Jun 13 '16 at 10:07
  • 2
    This doesn't work for me. I'm using Chrome version 55 on Windows 10. I put the script in several places (start of header, end of body, etc.) and I can still use the back button to go back to the previous page. – Victor Stoddard Jan 18 '17 at 21:37
  • I also could not make it work in Chrome at first but figured out how to make it work. It does not work if you put this in the footer of your main page (don't know why) but it does work if you put it inside the page that you're loading via ajax. It also works if you include it in the callback of jQuery's load function. $('#maincontent').load(filename,params,function() window.location.hash="no-back-button"; window.location.hash="Again-No-back-button"; window.onhashchange=function(){window.location.hash="no-back-button";}}); – Vincent Jul 09 '19 at 16:52
  • This doesn't work in Opera Version:68.0.3618.125 Works on Firefox 76.0.1 and Chrome 83.0.4103.97 though – lewis4u Jun 04 '20 at 16:12
  • Great solution! Works perfectly! – The_Long_Distance_Runner Feb 26 '21 at 11:47
42

For restricting the browser back event:

window.history.pushState(null, "", window.location.href);
window.onpopstate = function () {
    window.history.pushState(null, "", window.location.href);
};
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Fezal halai
  • 756
  • 7
  • 14
  • 2
    This works great on chrome!, why people are not voting as this is the best answer? – Tarık Seyceri Apr 29 '19 at 23:30
  • 2
    i just tested it using Windows 10 OS on the following browsers ( works great ) Chrome Version 74.0.3729.108 (Official Build) (64-bit) Chrome Canary Version 76.0.3780.0 (Official Build) canary (32-bit) Chromium Version 66.0.3355.0 (Developer Build) (64-bit) Firefox 66.0.3 (64-bit) EDGE IE 11 Safari 5.1.7 – Tarık Seyceri Apr 29 '19 at 23:39
  • 2
    @TarıkSeyceri because this only works on browsers that a) support the history API b) the page is actually using the history API to manage state – givanse Aug 22 '19 at 18:11
  • 2
    Not working anymore in Chrome after Version 75. See: https://support.google.com/chrome/thread/8721521?hl=en – gene b. Jan 27 '20 at 17:00
34

How to block coming backwards functionality:

history.pushState(null, null, location.href);
window.onpopstate = function () {
  history.go(1);
};
Aditya
  • 1,132
  • 1
  • 9
  • 28
  • 23
    While this may be a valid answer, you are much more likely to help others by explaining what the code does and how it works. Code-only answers tend to receive less positive attention and aren't as useful as other answers. – Aurora0001 Nov 24 '16 at 16:13
  • Tested on Chrome, Firefox, IE and Edge. It works well. You saved me. – Felix Htoo May 22 '20 at 05:20
  • Tested on Chrome 91 and it works perfectly. It'll be better if you explain what happened here as mentioned by @Aurora0001 . Good answer getting low vote. – umekalu Jun 16 '21 at 16:52
  • You can find an explanation of this snippet here: https://medium.com/codex/angular-guards-disabling-browsers-back-button-for-specific-url-fdf05d9fe155#4f13 – Vasileios Kagklis Aug 09 '22 at 23:10
33

This code will disable the back button for modern browsers which support the HTML5 History API. Under normal circumstances, pushing the back button goes back one step, to the previous page. If you use history.pushState(), you start adding extra sub-steps to the current page. The way it works is, if you were to use history.pushState() three times, then start pushing the back button, the first three times it would navigate back in these sub-steps, and then the fourth time it would go back to the previous page.

If you combine this behaviour with an event listener on the popstate event, you can essentially set up an infinite loop of sub-states. So, you load the page, push a sub-state, then hit the back button, which pops a sub-state and also pushes another one, so if you push the back button again it will never run out of sub-states to push. If you feel that it's necessary to disable the back button, this will get you there.

history.pushState(null, null, 'no-back-button');
window.addEventListener('popstate', function(event) {
  history.pushState(null, null, 'no-back-button');
});
Jeremy Warne
  • 3,437
  • 2
  • 30
  • 28
  • 3
    On any browser, try a page Refresh/Reload after this, and you'll get stuck on a "Page not found" error, as it tries to find a page named `no-back-button`... (The browser is also likely to show `no-back-button` in the address bar too, which seems ugly.) To be fair, this is not the only solution here which suffers from this. The 3rd argument to `history.pushState()` is a _url_, and must be the url of your current page: use `location.href` instead. – JonBrave Dec 17 '15 at 14:26
  • 4
    This worked for me. Just change 'no-back-button' to "window.top.location.pathname + window.top.location.search" and it will stay the name of the page you are on, even in refresh – Steve Mar 21 '16 at 16:28
  • Among others, this worked for me, upvote. Refer to http://stackoverflow.com/questions/19926641/how-to-disable-back-button-in-browser-using-javascript/25665232#25665232. – user2171669 Dec 14 '16 at 16:40
  • I've explored many cases, and this is the best solution for 1-page site – djdance Aug 25 '18 at 07:49
  • This is a very bad solution because you're changing the URL, so if you hit back and forwards a few times chrome will redirect to a path that doesn't exist – Tallboy Jan 04 '20 at 22:23
  • Not working anymore in Chrome after Version 75. See: https://support.google.com/chrome/thread/8721521?hl=en – gene b. Jan 27 '20 at 17:00
21

None of the most-upvoted answers worked for me in Chrome 79. It looks like Chrome changed its behavior with respect to the Back button after version 75. See here:

https://support.google.com/chrome/thread/8721521?hl=en

However, in that Google thread, the answer provided by Azrulmukmin Azmi at the very end did work. This is his solution.

<script>
    history.pushState(null, document.title, location.href);
    history.back();
    history.forward();
    window.onpopstate = function () {
        history.go(1);
    };
</script>

The problem with Chrome is that it doesn't trigger onpopstate event unless you make browser action ( i.e. call history.back). That's why I've added those to script.

I don't entirely understand what he wrote, but apparently an additional history.back() / history.forward() is now required for blocking Back in Chrome 75+.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
gene b.
  • 10,512
  • 21
  • 115
  • 227
  • After searching high & low this finally worked on Android browsers as well, where for some reason the browser's back button event wasn't detected with any other scripts I tried. Thank you, thank you, thank you again! Tested and working fine under Chrome 83 both desktop and mobile! Gene, you're a lifesaver! – Ivan Jun 04 '20 at 19:04
  • Works even if user has not clicked anywhere in the page. Thanks! – Garvit Jain Jul 31 '20 at 06:42
  • Thank you so much! This works in any browsers as well in mobile browsers! Worked like charm. Keep it up! :) – not_null Oct 05 '20 at 02:18
  • Still work fine, but after I have upgraded my browser to version 87.0.4280.66 (Official Build) (64-bit), it not work. Any work around for it? – Ninh Le Nov 20 '20 at 05:24
  • 1
    For some reason it did not work for me if the page had been loaded and no navigation had happened (still on landing page, on Android/chrome 89). What I did was do a redirect to a different URL on the landing URL. If the user clicks on back on that first page, then a reload happens, but at least I am still on my site. If back is clicked after any navigation, then there is indeed no action taken, no artifacts. – Will59 Mar 27 '21 at 15:36
  • This has been working great for me for a long time and suddenly today it just causes constant reloading of the page! (I'm in Firefox Dev 94.0) – Lisa DeBruine Oct 11 '21 at 12:38
17

React

For modal component in React project, the open or close of the modal, controlling browser back is a necessary action.

  • The stopBrowserBack: the stop of the browser back button functionality, also get a callback function. This callback function is what you want to do:

    const stopBrowserBack = callback => {
      window.history.pushState(null, "", window.location.href);
      window.onpopstate = () => {
        window.history.pushState(null, "", window.location.href);
        callback();
      };
    };
    
  • The startBrowserBack: the revival of the browser back button functionality:

    const startBrowserBack = () => {
      window.onpopstate = undefined;
      window.history.back();
    };
    

The usage in your project:

handleOpenModal = () =>
  this.setState(
    { modalOpen: true },
    () => stopBrowserBack(this.handleCloseModal)
  );

handleCloseModal = () =>
  this.setState(
    { modalOpen: false },
    startBrowserBack
  );
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
14

This is the way I could it accomplish it.

Weirdly, changing window.location didn't work out fine in Google Chrome and Safari.

It happens that location.hash doesn't create an entry in the history for Chrome and Safari. So you will have to use the pushstate.

This is working for me in all browsers.

history.pushState({ page: 1 }, "title 1", "#nbb");
window.onhashchange = function (event) {
    window.location.hash = "nbb";
};
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sanchitos
  • 8,423
  • 6
  • 52
  • 52
11
history.pushState(null, null, document.URL);
window.addEventListener('popstate', function () {
    history.pushState(null, null, document.URL);
});

This JavaScript code does not allow any user to go back (works in Chrome, Firefox, Internet Explorer, and Edge).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Surajit Mitra
  • 414
  • 8
  • 15
10

This article on jordanhollinger.com is the best option I feel. Similar to Razor's answer but a bit clearer. Code below; full credits to Jordan Hollinger:

Page before:

<a href="/page-of-no-return.htm#no-back>You can't go back from the next page</a>

Page of no return's JavaScript:

// It works without the History API, but will clutter up the history
var history_api = typeof history.pushState !== 'undefined'

// The previous page asks that it not be returned to
if ( location.hash == '#no-back' ) {
  // Push "#no-back" onto the history, making it the most recent "page"
  if ( history_api ) history.pushState(null, '', '#stay')
  else location.hash = '#stay'

  // When the back button is pressed, it will harmlessly change the url
  // hash from "#stay" to "#no-back", which triggers this function
  window.onhashchange = function() {
    // User tried to go back; warn user, rinse and repeat
    if ( location.hash == '#no-back' ) {
      alert("You shall not pass!")
      if ( history_api ) history.pushState(null, '', '#stay')
      else location.hash = '#stay'
    }
  }
}
dav_i
  • 27,509
  • 17
  • 104
  • 136
  • There isn't any current user by the name "Razor". Which answer is referred to? – Peter Mortensen Dec 14 '20 at 22:17
  • I think [this is a better answer](https://stackoverflow.com/questions/12381563/how-can-i-stop-the-browser-back-button-using-javascript/34337617#34337617) in 2022. Easier to understand and less code. If you are using SSR, you will need to add a check for typeof window !== 'undefined' to avoid issues on the server. – Chanoch Feb 22 '22 at 23:49
10
<html>
<head>
    <title>Disable Back Button in Browser - Online Demo</title>
    <style type="text/css">
        body, input {
            font-family: Calibri, Arial;
        }
    </style>
    <script type="text/javascript">
        window.history.forward();
        function noBack() {
            window.history.forward();
        }
    </script>
</head>
<body onload="noBack();" onpageshow="if (event.persisted) noBack();" onunload="">
    <H2>Demo</H2>
    <p>This page contains the code to avoid Back button.</p>
    <p>Click here to Goto <a href="noback.html">NoBack Page</a></p>
</body>
</html>
informatik01
  • 16,038
  • 10
  • 74
  • 104
Ashwin Patil
  • 1,307
  • 1
  • 23
  • 27
  • Is there some documentation somewhere for `event.persisted`? – Muhd Jul 06 '13 at 01:56
  • 1
    Here is the link found for your question. Find it [here](https://www.w3schools.com/jsref/event_pagetransition_persisted.asp) @Muhd – rbashish Aug 03 '17 at 04:56
9

This code was tested with the latest Chrome and Firefox browsers.

<script type="text/javascript">
    history.pushState(null, null, location.href);
    history.back();
    history.forward();
    window.onpopstate = function () { history.go(1); };
</script>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
5

Try it with ease:

history.pushState(null, null, document.title);
window.addEventListener('popstate', function () {
    history.pushState(null, null, document.title);
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Lakhan
  • 12,328
  • 3
  • 19
  • 28
3

Very simple and clean function to break the back arrow without interfering with the page afterward.

Benefits:

  • Loads instantaneously and restores original hash, so the user isn't distracted by URL visibly changing.
  • The user can still exit by pressing back 10 times (that's a good thing), but not accidentally
  • No user interference like other solutions using onbeforeunload
  • It only runs once and doesn't interfere with further hash manipulations in case you use that to track state
  • Restores original hash, so almost invisible.
  • Uses setInterval, so it doesn't break slow browsers and always works.
  • Pure JavaScript, does not require HTML5 history, works everywhere.
  • Unobtrusive, simple, and plays well with other code.
  • Does not use unbeforeunload which interrupts user with modal dialog.
  • It just works without fuss.

Note: some of the other solutions use onbeforeunload. Please do not use onbeforeunload for this purpose, which pops up a dialog whenever users try to close the window, hit backarrow, etc. Modals like onbeforeunload are usually only appropriate in rare circumstances, such as when they've actually made changes on screen and haven't saved them, not for this purpose.

How It Works

  1. Executes on page load
  2. Saves your original hash (if one is in the URL).
  3. Sequentially appends #/noop/{1..10} to the hash
  4. Restores the original hash

That's it. No further messing around, no background event monitoring, nothing else.

Use It In One Second

To deploy, just add this anywhere on your page or in your JavaScript code:

<script>
    /* Break back button */
    window.onload = function(){
      var i = 0;
      var previous_hash = window.location.hash;
      var x = setInterval(function(){
        i++;
        window.location.hash = "/noop/" + i;
        if (i==10){
          clearInterval(x);
          window.location.hash = previous_hash;
        }
      }, 10);
    }
</script>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
fatal_error
  • 5,457
  • 2
  • 18
  • 18
3

You can just put a small script and then check. It won't allow you to visit previous page.

This is done in JavaScript.

<script type="text/javascript">
    function preventbackbutton() { window.history.forward(); }
    setTimeout("preventbackbutton()", 0);
    window.onunload = function () { null };
</script>

The window.onunload function fires when you try to visit back or previous page through browser.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rohan Rao
  • 2,505
  • 3
  • 19
  • 39
2

You simply cannot and should not do this. However, this might be helpful:

<script type = "text/javascript" >
    history.pushState(null, null, 'pagename');
    window.addEventListener('popstate', function(event) {
        history.pushState(null, null, 'pagename');
    });
</script>

This works in my Google Chrome and Firefox.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shailendra Sharma
  • 6,976
  • 2
  • 28
  • 48
2

This seems to have worked for us in disabling the back button on the browser, as well as the backspace button taking you back.

history.pushState(null, null, $(location).attr('href'));
window.addEventListener('popstate', function () {
    history.pushState(null, null, $(location).attr('href'));
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jgabb
  • 542
  • 1
  • 4
  • 20
2

In a modern browser this seems to work:

// https://developer.mozilla.org/en-US/docs/Web/API/History_API
let popHandler = () => {
  if (confirm('Go back?')) {
    window.history.back() 
  } else {
    window.history.forward()
    setTimeout(() => {
      window.addEventListener('popstate', popHandler, {once: true})
    }, 50) // delay needed since the above is an async operation for some reason
  }
}
window.addEventListener('popstate', popHandler, {once: true})
window.history.pushState(null,null,null)
2

I had this problem with React (class component).

And I solved it easily:

componentDidMount() {
    window.addEventListener("popstate", e => {
        this.props.history.goForward();
    }
}

I've used HashRouter from react-router-dom.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kid
  • 1,160
  • 2
  • 14
  • 31
2

Just run code snippet right away and try going back

history.pushState(null, null, window.location.href);
history.back();
window.onpopstate = () => history.forward();
Saksham Chaudhary
  • 519
  • 1
  • 4
  • 14
1
<script src="~/main.js" type="text/javascript"></script>

<script type="text/javascript">
    window.history.forward();

    function noBack() {
        window.history.forward();
    }
</script>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user3789888
  • 123
  • 1
  • 2
1

Try this to prevent the backspace button in Internet Explorer which by default acts as "Back":

<script language="JavaScript">
    $(document).ready(function() {
    $(document).unbind('keydown').bind('keydown', function (event) {
        var doPrevent = false;

        if (event.keyCode === 8 ) {
            var d = event.srcElement || event.target;
            if ((d.tagName.toUpperCase() === 'INPUT' &&
                 (
                     d.type.toUpperCase() === 'TEXT'     ||
                     d.type.toUpperCase() === 'PASSWORD' ||
                     d.type.toUpperCase() === 'FILE'     ||
                     d.type.toUpperCase() === 'EMAIL'    ||
                     d.type.toUpperCase() === 'SEARCH'   ||
                     d.type.toUpperCase() === 'DATE' )
                ) ||
                d.tagName.toUpperCase() === 'TEXTAREA') {

                     doPrevent = d.readOnly || d.disabled;
                }
                else {
                    doPrevent = true;
                }
            }

            if (doPrevent) {
                event.preventDefault();
            }

            try {
                document.addEventListener('keydown', function (e) {
                    if ((e.keyCode === 13)) {
                        //alert('Enter keydown');
                        e.stopPropagation();
                        e.preventDefault();
                    }
                }, true);
            }
            catch (err) {
            }
        });
    });
</script>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ajit Kamble
  • 153
  • 1
  • 12
1

It's basically assigning the window's "onbeforeunload" event along with the ongoing document 'mouseenter' / 'mouseleave' events so the alert only triggers when clicks are outside the document scope (which then could be either the back or forward button of the browser)

    $(document).on('mouseenter', function(e) { 
            window.onbeforeunload = null; 
        }
    );
    
    $(document).on('mouseleave', function(e) { 
            window.onbeforeunload = function() { return "You work will be lost."; };
        }
    );
Muhammad Ali
  • 956
  • 3
  • 15
  • 20
0

I create one HTML page (index.html). I also create a one (mechanism.js) inside a script folder / directory. Then, I lay all my content inside of (index.html) using form, table, span, and div tags as needed. Now, here's the trick that will make back / forward do nothing!

First, the fact that you have only one page! Second, the use of JavaScript with span / div tags to hide and display content on the same page when needed via regular links!

Inside 'index.html':

<td width="89px" align="right" valign="top" style="letter-spacing:1px;">
    <small>
        <b>
            <a href="#" class="traff" onClick="DisplayInTrafficTable();">IN</a>&nbsp;
        </b>
    </small>
    [&nbsp;<span id="inCountSPN">0</span>&nbsp;]
</td>

Inside 'mechanism.js':

function DisplayInTrafficTable()
{
    var itmsCNT = 0;
    var dsplyIn = "";
    for (i=0; i<inTraffic.length; i++)
    {
        dsplyIn += "<tr><td width='11'></td><td align='right'>" + (++itmsCNT) + "</td><td width='11'></td><td><b>" + inTraffic[i] + "</b></td><td width='11'></td><td>" + entryTimeArray[i] + "</td><td width='11'></td><td>" + entryDateArray[i] + "</td><td width='11'></td></tr>";
    }
    document.getElementById('inOutSPN').innerHTML =
        "" +
        "<table border='0' style='background:#fff;'><tr><th colspan='21' style='background:#feb;padding:11px;'><h3 style='margin-bottom:-1px;'>INCOMING TRAFFIC REPORT</h3>" +
        DateStamp() +
        "&nbsp;&nbsp;-&nbsp;&nbsp;<small><a href='#' style='letter-spacing:1px;' onclick='OpenPrintableIn();'>PRINT</a></small></th></tr><tr style='background:#eee;'><td></td><td><b>###</b></td><td></td><td><b>ID #</b></td><td></td><td width='79'><b>TYPE</b></td><td></td><td><b>FIRST</b></td><td></td><td><b>LAST</b></td><td></td><td><b>PLATE #</b></td><td></td><td><b>COMPANY</b></td><td></td><td><b>TIME</b></td><td></td><td><b>DATE</b></td><td></td><td><b>IN / OUT</b></td><td></td></tr>" +
        dsplyIn.toUpperCase() +
        "</table>" +
        "";
    return document.getElementById('inOutSPN').innerHTML;
}

It looks hairy, but note the function names and calls, embedded HTML, and the span tag id calls. This was to show how you can inject different HTML into same span tag on same page! How can Back/Forward affect this design? It cannot, because you are hiding objects and replacing others all on the same page!

How can we hide and display? Here goes:

Inside functions in ' mechanism.js ' as needed, use:

document.getElementById('textOverPic').style.display = "none"; //hide
document.getElementById('textOverPic').style.display = "";     //display

Inside ' index.html ' call functions through links:

<img src="images/someimage.jpg" alt="" />
<span class="textOverPic" id="textOverPic"></span>

and

<a href="#" style="color:#119;font-size:11px;text-decoration:none;letter-spacing:1px;" onclick="HiddenTextsManager(1);">Introduction</a>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

In my case this was a shopping order. So I disabled the button. When the user clicked back, the button was disabled still. When they clicked back one more time, and then clicked a page button to go forward. I knew their order was submitted and skipped to another page.

In the case when the page actually refreshed which would make the button (theoretically), available; I was then able to react in the page load that the order was already submitted and redirected then too.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Valamas
  • 24,169
  • 25
  • 107
  • 177
0

Just set location.hash="Something". On pressing the back button, the hash will get removed from the URL, but the page won't go back.

This method is good for preventing going back accidentally, but for security purposes you should design your backend for preventing reanswering.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

Some of the solutions here will not prevent a back event from occurring - they let a back event happen (and data held about the page in the browsers memory is lost) and then they play a forward event to try and hide the fact that a back event just happened. Which is unsuccessful if the page held transient state.

I wrote this solution for React (when react router is not being used), which is based on vrfvr's answer.

It will truly stop the back button from doing anything unless the user confirms a popup:

  const onHashChange = useCallback(() => {
    const confirm = window.confirm(
      'Warning - going back will cause you to loose unsaved data. Really go back?',
    );
    window.removeEventListener('hashchange', onHashChange);
    if (confirm) {
      setTimeout(() => {
        window.history.go(-1);
      }, 1);
    } else {
      window.location.hash = 'no-back';
      setTimeout(() => {
        window.addEventListener('hashchange', onHashChange);
      }, 1);
    }
  }, []);

  useEffect(() => {
    window.location.hash = 'no-back';
    setTimeout(() => {
      window.addEventListener('hashchange', onHashChange);
    }, 1);
    return () => {
      window.removeEventListener('hashchange', onHashChange);
    };
  }, []);
kohloth
  • 742
  • 1
  • 7
  • 21
0

This code is full javascript. Put this on your home page or whatever you need when someon goes back it brings them to the page they were previously on.

<script type="text/javascript"> 
        function preventBack() { 
            window.history.forward();  
        } 
          
        setTimeout("preventBack()", 0); 
          
        window.onunload = function () { null }; 
    </script>
user9384
  • 27
  • 10
0

This is the first hit I get for the Google query "disable back button". My use case is a little different than the original posted question. I need to "disable the back button" for a user that has logged of of a secured web site (i.e. prevent a user from logging off and then another user being able to view information from the previous user by hitting the back button).

In short, the goal here is to prevent a user from seeing the applications page after the logged in user has logged off.

This can be achieved by adding the code shown below to the pages in the authenticated application.

A full example using Apache Shiro is available here:

https://github.com/NACHC-CAD/web-security-example/releases/tag/v2.0.0

<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />
<meta http-equiv="CACHE-CONTROL" content="NO-CACHE" />

<script>
    if(performance.navigation.type == 2){
        console.log("Doing reload");   
        location.reload(true);
        console.log("Done with reload");
    }
    console.log("Script loaded.")
</script>
John
  • 3,458
  • 4
  • 33
  • 54
0

Try with this: Suppose there are two pages Page1 and Page2 and Page1 redirects to Page2

to prevent user from visiting Page1 using the back button you will need to place the above script in the Page1

$(document).ready(async function (){
    history.pushState(null, null, location.href);
    window.onpopstate = function () {
        history.go(1);
    };
})
Dey
  • 842
  • 9
  • 21
0

Based on answer @Franklin Innocent F

Solution for Kotlin/JS (React):

import org.w3c.dom.events.Event
import kotlin.browser.document
import kotlin.browser.window

...
override fun componentDidMount() {
    window.history.pushState(null, "", window.location.href)
    window.history.back()
    window.history.forward()
    window.addEventListener("popstate", browserBackButtonHandler)
}

...
private val browserBackButtonHandler: (Event?) -> Unit = {
    window.history.go(1)
}
alexrnov
  • 2,346
  • 3
  • 18
  • 34
0

If you are using angular just use *ngIf=loggedout within a div or container div.

Set variable in component. If it's true show else router will redirect to home page. As per your configuration on router file.

This work for login and log out using username for example. As for other account related pages or internal pages it will be a bit hard to prevent. You might need to disable the whole browser nav tab.

Neo Sono
  • 186
  • 1
  • 4
  • 18
0

Having gone through most of the existing answers, there is no solution that works in chrome.

The idea is make the browser to move forward one page in the session history, effectively preventing leaving this page using the back browser button. You do this by invoking the History.forward() method, by placing the following line in the page.

window.history.forward();

I found this solution at mdn web docs and it works in chrome.

owino
  • 151
  • 1
  • 3
  • 11
0

If you use React, you can use NPM module: use-history-back-trap. This is a custom React hook which intercepts back navigation and allows to resume it later if needed.

Usage is super simple:

const SomeFunctionalReactComponent = () => {
   useHistoryBackTrap(approveNavigation)
   // ...
}

where approveNavigation is your function which returns true (or Promise) when you want to proceed with back navigation.

RandomX
  • 189
  • 1
  • 3
0

If you link to your exam page using window.location.replace("ExamPage.html") this will remove anything for the back button to go back to.

Example button link... input type="button" onClick="window.location.replace('ExamPage.html');" value="Exam Page"

Sorry the chevrons are missing around the button example. When I add them, the example is not shown.

Tel
  • 81
  • 4
0
<script>
history.pushState(null, null, location.href);
window.onpopstate = function () {
    history.go(1);
};
</script>

Use this code in yr html to prevent back button

Gajender Singh
  • 1,285
  • 14
  • 13
-1

Here is another way to proceed. Instead of just trying to avoid the Back button functionality (which doesn't work reliably) we can add short SessionStorage conditions.

Say we have three different pages (page1, page2, and page3). On each page we got a link to click to acceed to the next one and we don't want the user to be able to go back to the previous page.

On the first page (page1.html) we create an SI (sessionStorage Item) with a dummy "prev" code and another one with "page1" code (SI "now"):

  PAGE 1  <button onclick="goto()">PAGE 2</button>

  -------------------

  let thispage = '1' // Or 123456 if preferred or make sense

  // You can replace this fixed 'thispage' value on each page with a script counting the clicks
  // or any other way to increase its value, i.e., thispage++
  // or what you want, even counting the url.length (lol)

  sessionStorage.setItem('prev', '0') // Dummy code
  sessionStorage.setItem('now', thispage)

  // You can here make this page unreachable with page2/page3 SI same conditions

  function goto(){
      window.location = "page2.html"
  }

On page2.html we use the usual NoBack script (if it works) and update SIs only if we're coming from page1:

  PAGE 2  <button onclick="goto()">PAGE 3</button>

  -------------------

  // If it works, let it work :-)

  history.pushState(null, null, location.href);
  history.back();
  history.forward();
  window.onpopstate = function () {
      history.go(1);
  };

  // else

  let thispage = '2' // 456789
  let thisprev = sessionStorage.getItem('now')
  if(sessionStorage.getItem('prev')==thispage) {
      console.log('USER is back on PAGE 2')
      setTimeout(function() { goto() }, 1000); // Remove log + setTimeout
  }
  if(thisprev !== thispage) {
      if(thisprev < thispage) {
          console.log('USER is coming from PAGE 1')
          sessionStorage.setItem('prev', thisprev)
          sessionStorage.setItem('now', thispage)
      }
      else {
          console.log('USER try to reload this page')
          setTimeout(function() { goto() }, 1000);
      }
  }

  function goto(){
      window.location = "page3.html"
  }

And on page3.html:

  PAGE 3  <button onclick="goto()">BACK TO PAGE 1</button>

  -------------------

  history.pushState(null, null, location.href);
  history.back();
  history.forward();
  window.onpopstate = function () {
      history.go(1);
  };

  let thispage = '3' // 999999
  let thisprev = sessionStorage.getItem('now')
  if(sessionStorage.getItem('prev') == thispage) {
      goto()
  }
  if(thisprev !== thispage) {
      if(thisprev < thispage) {
          sessionStorage.setItem('prev', thisprev)
          sessionStorage.setItem('now', thispage)
      }
      else {
          goto()
      }
  }
  function goto(){
      window.location = "page1.html" // Reinit test
  }

The advantage is that even if the user manually reloads the previous page (if he had time to see and remember the URL) it still works. It was not tested on all devices, but seems to work fine on Firefox + Chrome + Edge Windows 10 and Firefox + Chrome on OS X.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Wolden
  • 195
  • 1
  • 12
-3
//"use strict";
function stopBackSpace(e) {
    var ev = e || window.event;
    var obj = ev.target || ev.srcElement;
    var t = obj.type || obj.getAttribute('type');

    var vReadOnly = obj.getAttribute('readonly');
    var vEnabled = obj.getAttribute('enabled');
    // null
    vReadOnly = (vReadOnly == null) ? false : vReadOnly;
    vEnabled = (vEnabled == null) ? true : vEnabled;
    // when click Backspace,judge the type of obj.

    var flag1 = ((t == 'password' || t == 'text' || t == 'textarea') && ((vReadOnly == true || vReadOnly == 'readonly') || vEnabled != true)) ? true : false;

    var flag2 = (t != 'password' && t != 'text' && t != 'textarea') ? true : false;

    if (flag2) {
        e.keyCode = 0;
        e.cancelBubble = true;
        return false;
    }
    if (flag1) {
        e.keyCode = 0;
        e.cancelBubble = true;
        return false;
    }
}
if (typeof($) == 'function') {
    $(function() {
        $(document).keydown(function(e) {
            if (e.keyCode == 8) {
                return stopBackSpace(e);
            }
        });
    });
} else {
    document.onkeydown = stopBackSpace;
}
Chauncey.Zhong
  • 117
  • 1
  • 1
  • 6
  • 1 get the event object 2. to determine the event source type, as the judgment condition. 3.When the hit Backspace, the event source type for the password or single, and the readonly property to true or enabled property is false, then the backspace key failure. When hit Backspace, the source of the event types the password or single, is the backspace key failure – Chauncey.Zhong Jul 20 '17 at 10:03
  • 2
    The question is asking about using the Back Navigation Button not the backspace key. – Quentin Aug 21 '17 at 13:19