HTML Forms: How (and Why) to Prevent Double Form Submissions

When double clicking a submit button your form will be sent twice. Using JavaScript you can prevent this from happening, but wouldn’t it be nice if this behavior could be tweaked by use of an attribute on the <form>? If you think so, feel free to give this issue a thumbs up.

Today Sebastian wondered:

I quickly chimed in saying that I do tend to lock up forms when submitting them. Let me explain why …

~

I started locking up submitted forms as users of the apps I’m building reported that sometimes the actions they had taken — such as adding an entry — were performed twice. I took me some time to figure out what exactly was going on, but eventually I found out this was because they were double clicking the submit button of the forms. As they double clicked the button, the form got sent over twice. By locking up forms after their first submission, all successive submissions — such as those triggered by that second click of a double click — are ignored.

~

To prevent these extra form submissions from being made I don’t hijack the form with Ajax nor do I perform any other complicated things. I let the inner workings of the web and forms in the browser be: when pressing the submit button the browser will still collect all form data, build a new HTTP request, and execute that request.

What I simply do is extend the form’s capabilities by adding a flag — by means of a CSS class — onto the form to indicate whether it’s being submitted or not. I can then use this flag’s presence to deny any successive submissions, and also hook some CSS styles on. — Progressive Enhancement, Yay! 🎉

The code looks as follows:

 // Prevent Double Submits
document.querySelectorAll('form').forEach(form => {
	form.addEventListener('submit', (e) => {
		// Prevent if already submitting
		if (form.classList.contains('is-submitting')) {
			e.preventDefault();
		}
		
		// Add class to hook our visual indicator on
		form.classList.add('is-submitting');
	});
});

💡 Although the problem initially was a double click problem, we don’t listen for any clicks on the submit button but listen for the form’s submit event. This way our code not only works when clicking any of the submit buttons, but also when pressing enter to submit.

With that .is-submitting class in place, we can then attach some extra CSS onto the form to give the user visual feedback. Here’s a few examples:

See the Pen
Prevent Form Double Submits
by Bramus (@bramus)
on CodePen.

See the Pen
Prevent Form Double Submits (Alternative version)
by Bramus (@bramus)
on CodePen.

Note that this solution might not cover 100% of all possible scenarios, as it doesn’t take failing networks and other things that might go wrong into account. However, as I’m relying on the basic mechanisms of the web I think I can also rely on the browser to show that typical “Confirm Form Resubmission” interstitial should a timeout occur. Additionally, if need be, one could always unlock the form after a fixed amount of time. That way the user will be able to re-submit it again.

~

Dealing with double form submissions isn’t a new issue at all. You’ll find quite some results when running a few queries through Google — something I only found out after stumbling over the issue myself.

Back in 2015 (!) Mattias Geniar also pondered about this, after being pulled into the subject from a sysadmin view. Now, when even sysadmins are talking about an HTML/UX issue you know there’s something going on. This made me wonder why browsers behaved like that and how we could solve it:

As a result I decided to open an issue at the WHATWG HTML Standard repo, suggesting for a way to fix this at spec level:

An attribute on <form> to tweak this behavior – instead of having to rely on JavaScript – would come in handy and form a nice addition to the spec.

I see two options to go forward:

  1. Browsers/the standard keeps the current behavior and allow multiple submits. Developers must opt-in to prevent multiple submissions using a preventmultiplesubmits attribute.
  2. Browsers/the standard adjust the current behavior to only submit forms once. Developers must opt-in to allow multiple submissions using a allowmultiplesubmits attribute.

Initial response on the issue was very low, and it looks like this isn’t that big of a priority.

Back then I was more in favor of the second solution, but now I’m quite undecided as changing the default behavior — which has been around for ages — is quite tricky.

~

Another way that this issue could be fixed is at the browser level: if they were to treat double clicks on form submit buttons as single clicks, then the double click problem — but not the double submit problem — could also be taken care of.

To then attach styles to forms being submitted a CSS Pseudo Class :submitting would come in handy. Come to think of it, this Pseudo Class would be a quite nice addition to CSS in itself, no matter whether this double click issue gets solved or not.

~

Winging back to the addition to the HTML spec I suggested: If you do think it could be something the HTML spec could benefit from, feel free to add a thumbs up to the issue to indicate that you want this, or add an extra comment to it if you have more input on the subject.

Did this help you out? Like what you see?
Thank me with a coffee.

I don\'t do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

BuymeaCoffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Unless noted otherwise, the contents of this post are licensed under the Creative Commons Attribution 4.0 License and code samples are licensed under the MIT License

Join the Conversation

11 Comments

  1. hey, do you have an error in your example code?

    your if statement has to be “if (form.classList.contains(‘is-submitting’))” or am I wrong?

  2. I think there are many ways to deal with this. Using a flag in JS or using cookie or some kind of flags as hidden attribute in the form. It would be nice to have an attribute in form to indicate whether the form is of single submit or multiple submit. However there are many tags which HTML lacks, eg there is no name tag even though everything in world has some name. Think of all the extra code we write to validate the name.

    1. Going a bit off-topic here, but why would you validate a name?

      There are some fine examples out there where people were (wrongfully) prevented submitting a form because their name was “too short” (e.g. people with 2-character names) or “contained illegal characters” (e.g. people from France with a ç in their name) or …

  3. A css pseudo class could also help handle double-submits. One could have:

    form:submitting input[type=submit] {
    pointer-events: none;
    }

    1. Yes, that’s also suggested in the post 🙂

      Do note that this approach alone won’t prevent forms from being submitted twice entirely. It will only prevent you from submitting it twice with the mouse; you’ll still be able to hitting ENTER/RETURN to trigger an extra submission.

  4. For years it’s been one of question I am asking during interviews especially when someone applies for full stack position.
    Usually I am upset when no backend aspects are mentioned, especially that frontend fix can be simply worked around (or may simply not work as you wrote due to networking issues).
    To rephrase.. in any let’s say banking system only frontend solution will not be enough. In any big enough system it will mean you will have much less double submissions, but they still gonna be there.

  5. It seem’s to not working even with mouse
    form:submitting input[type=submit] {
    pointer-events: none;
    touch-action: none;
    }

Leave a comment

Leave a Reply to wlos Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.