How is the default submit button on an HTML form determined?

205,711

Solution 1

If you submit the form via JavaScript (i.e., formElement.submit() or anything equivalent), then none of the submit buttons are considered successful and none of their values are included in the submitted data. (Note that if you submit the form by using submitElement.click() then the submit that you had a reference to is considered active; this doesn't really fall under the remit of your question since here the submit button is unambiguous but I thought I'd include it for people who read the first part and wonder how to make a submit button successful via JavaScript form submission. Of course, the form's onsubmit handlers will still fire this way whereas they wouldn't via form.submit() so that's another kettle of fish...)

If the form is submitted by hitting Enter while in a non-textarea field, then it's actually down to the user agent to decide what it wants here. The specifications don't say anything about submitting a form using the Enter key while in a text entry field (if you tab to a button and activate it using space or whatever, then there's no problem as that specific submit button is unambiguously used). All it says is that a form must be submitted when a submit button is activated. It's not even a requirement that hitting Enter in e.g. a text input will submit the form.

I believe that Internet Explorer chooses the submit button that appears first in the source; I have a feeling that Firefox and Opera choose the button with the lowest tabindex, falling back to the first defined if nothing else is defined. There's also some complications regarding whether the submits have a non-default value attribute IIRC.

The point to take away is that there is no defined standard for what happens here and it's entirely at the whim of the browser - so as far as possible in whatever you're doing, try to avoid relying on any particular behaviour. If you really must know, you can probably find out the behaviour of the various browser versions, but when I investigated this a while back there were some quite convoluted conditions (which of course are subject to change with new browser versions) and I'd advise you to avoid it if possible!

Solution 2

HTML 4 does not make it explicit. The current HTML5 working draft specifies that the first submit button must be the default:

A form element's default button is the first submit button in tree order whose form owner is that form element.

If the user agent supports letting the user submit a form implicitly (for example, on some platforms hitting the "enter" key while a text field is focused implicitly submits the form), then doing so for a form whose default button has a defined activation behavior must cause the user agent to run synthetic click activation steps on that default button.

Solution 3

Andrezj's answer pretty much got it nailed... but here's an easy cross-browser solution.

Take a form like this:

<form>
    <input/>
    <button type="submit" value="some non-default action"/>
    <button type="submit" value="another non-default action"/>
    <button type="submit" value="yet another non-default action"/>

    <button type="submit" value="default action"/>
</form>

and refactor to this:

<form>
    <input/>

    <button style="overflow: visible !important; height: 0 !important; width: 0 !important; margin: 0 !important; border: 0 !important; padding: 0 !important; display: block !important;" type="submit" value="default action"/>

    <button type="submit" value="some non-default action"/>
    <button type="submit" value="another non-default action"/>
    <button type="submit" value="yet another non-default action"/>
    <button type="submit" value="still another non-default action"/>

    <button type="submit" value="default action"/>
</form>

Since the W3C specification indicates multiple submit buttons are valid, but omits guidance as to how the user-agent should handle them, the browser manufacturers are left to implement as they see fit. I've found they'll either submit the first submit button in the form, or submit the next submit button after the form field that currently has focus.

Unfortunately, simply adding a style of display: none; won't work because the W3C spec indicates any hidden element should be excluded from user interactions. So hide it in plain sight instead!

Above is an example of the solution I ended up putting into production. Hitting the enter key triggers the default form submission is behavior as expected, even when other non-default values are present and precede the default submit button in the DOM. Bonus for mouse/keyboard interaction with explicit user inputs while avoiding JavaScript handlers.

Note: tabbing through the form will not display focus for any visual element yet will still cause the invisible button to be selected. To avoid this issue, simply set tabindex attributes accordingly and omit a tabindex attribute on the invisible submit button. While it may seem out of place to promote these styles to !important, they should prevent any framework or existing button styles from interfering with this fix. Also, those inline styles are definitely poor form, but we're proving concepts here... not writing production code.

Solution 4

This can now be solved using Flexbox:

HTML

<form>
    <h1>My Form</h1>
    <label for="text">Input:</label>
    <input type="text" name="text" id="text"/>

    <!-- Put the elements in reverse order -->
    <div class="form-actions">
        <button>Ok</button> <!-- Our default action is first -->
        <button>Cancel</button>
    </div>
</form>

CSS

.form-actions {
    display: flex;
    flex-direction: row-reverse; /* Reverse the elements inside */
}

Explanation

Using Flexbox, we can reverse the order of the elements in a container that uses display: flex by also using the CSS rule: flex-direction: row-reverse. This requires no CSS or hidden elements. For older browsers that do not support Flexbox, they still get a workable solution but the elements will not be reversed.

Demo

http://codepen.io/Godwin/pen/rLVKjm

Solution 5

I think this post would help if someone wants to do it with jQuery:

http://greatwebguy.com/programming/dom/default-html-button-submit-on-enter-with-jquery/

The basic solution is:

$(function() {
    $("form input").keypress(function (e) {
    if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
        $('input[type=submit].default').click();
        return false;
    }
    else {
        return true;
    }
    });
});

And another I liked was:

jQuery(document).ready(function() {
    $("form input, form select").live('keypress', function (e) {
        if ($(this).parents('form').find('button[type=submit].default, input[type=submit].default').length <= 0)
            return true;

        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
            $(this).parents('form').find('button[type=submit].default, input[type=submit].default').click();
            return false;
        }
        else {
            return true;
        }
    });
});
Share:
205,711

Related videos on Youtube

Stewart
Author by

Stewart

Updated on September 26, 2021

Comments

  • Stewart
    Stewart almost 3 years

    If a form is submitted but not by any specific button, such as

    • by pressing Enter
    • using HTMLFormElement.submit() in JS

    how is a browser supposed to determine which of multiple submit buttons, if any, to use as the one pressed?

    This is significant on two levels:

    • calling an onclick event handler attached to a submit button
    • the data sent back to the web server

    My experiments so far have shown that:

    • when pressing Enter, Firefox, Opera and Safari use the first submit button in the form
    • when pressing Enter, IE uses either the first submit button or none at all depending on conditions I haven't been able to figure out
    • all these browsers use none at all for a JS submit

    What does the standard say?

    If it would help, here's my test code (the PHP is relevant only to my method of testing, not to my question itself)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Test</title>
    </head>
    
    <body>
    
    <h1>Get</h1>
    <dl>
    <?php foreach ($_GET as $k => $v) echo "<dt>$k</dt><dd>$v</dd>"; ?>
    </dl>
    
    <h1>Post</h1>
    <dl>
    <?php foreach ($_POST as $k => $v) echo "<dt>$k</dt><dd>$v</dd>"; ?>
    </dl>
    
    <form name="theForm" method="<?php echo isset($_GET['method']) ? $_GET['method'] : 'get'; ?>" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>">
        <input type="text" name="method" />
        <input type="submit" name="action" value="Button 1" onclick="alert('Button 1'); return true" />
        <input type="text" name="stuff" />
        <input type="submit" name="action" value="Button 2" onclick="alert('Button 2'); return true" />
        <input type="button" value="submit" onclick="document.theForm.submit();" />
    </form>
    
    </body></html>
    
  • Stewart
    Stewart about 15 years
    Re para 2: My basic question was whether there's anything in any spec to the effect of "If the browser provides any means of submitting a form without specifying a submit control...". But I gather from David's reply that there isn't. My point about IE was that sometimes pressing Enter submits a form and doesn't set any submit button. A consequence is that, if you have multiple forms submitting to the same script, you can't rely on submit buttons to distinguish them. This came up in the project I'm working on.
  • Stewart
    Stewart about 15 years
    Indeed, but that begs this question: stackoverflow.com/questions/541869/…
  • BalusC
    BalusC over 14 years
    Bad idea. Your form won't work with JS disabled. JS ought to be used unobtrusively.
  • graphic
    graphic over 14 years
    Very few browsers have JS turned off by default, even the ones on iPods! On the form I was citing, JS off would render it useless! So much hinges on JS running.
  • Stewart
    Stewart over 14 years
    Turned off by default or not, those who have JS disabled ought not to have to switch it on just to get around such a silly little snag as this.
  • Stewart
    Stewart about 13 years
    But is this behaviour specified by the standard? And can browsers be trusted to implement it correctly?
  • gcb
    gcb about 13 years
    good question. i've tested it to work on all A browsers (from yui browser matrix) and it's the most consitent i could get in real life (regardless of what the standards specify)
  • Ben
    Ben about 13 years
    what kind of form has 11 submit buttons?? (curiosity)
  • ThiefMaster
    ThiefMaster about 13 years
    Additionally your code sucks. language needs to die, the proper attribute is type="text/javascript"
  • leemes
    leemes over 12 years
    @mhenry1384: there are a lot of reasons why you should NOT restrict your user in any way (when possible). Your statement is the same like saying users who use IE6 need to die - There are still users being dependent on which browser (and setting) they use, e.g. in a lot of companies. So in my opinion, one should ALWAYS consider users restricted to IE6 and JS disabled - at least by providing a workaround for them.
  • Arjan
    Arjan over 12 years
    jQuery.Event always has its .wich attribute. Also no need to fall back to DOM's .keyCode (or .charCode for that matter).
  • Samantha Branham
    Samantha Branham over 12 years
    The biggest reason I see validating unobtrusive Javascript is that obtrusive Javascript tends to be fiddly. I'm not sure how to qualify what I'm thinking, but when I see pages absolutely reliant on JS, I'm also betting I can do some tricky stuff with my DOM and do something unintended on the server.
  • Stefan Haberl
    Stefan Haberl over 12 years
    Thanks. Stumbled across the display: none problem as well. Instead of minimizing the button you could also move it out of the page by surronding it with a <div style="position: fixed; left: -1000px; top: -1000px />. Just one more thing to concern: Just minimizing or moving away the button from the page flow with CSS might bring up WAI issues, because screen readers will still see the default button.
  • Nathan
    Nathan about 12 years
    THANK YOU @James for this detailed answer.
  • Stewart
    Stewart almost 12 years
    @mhenry1384 That's like saying people who wear glasses, use wheelchairs, etc. need to die.
  • soletan
    soletan almost 12 years
    Another issue regarding jQuery here is the unneccessary double query. Since there is no need to return true, additionally, the jQuery version gets really clear and short on integrating reductions advised by Arjan before.
  • Stewart
    Stewart over 11 years
    What's the fallback for users who have JS disabled?
  • Macumbaomuerte
    Macumbaomuerte about 11 years
    this worked for me, thanks. I had to add this for the button border:none; to make it complitely disapear
  • Stewart
    Stewart almost 11 years
    Type "button" does not cause the form to submit. It's used only to trigger client-side scripts.
  • Jesús Carrera
    Jesús Carrera almost 11 years
    exactly, that's why the browser skips it when you hit enter, and the one with type "submit" gets executed. You can use the one with type "button" to do anything else on click for example. Please remove the negative vote.
  • Stewart
    Stewart almost 11 years
    The question was about multiple submit buttons.
  • Jesús Carrera
    Jesús Carrera almost 11 years
    My example is totally valid for multiple submit buttons. The one with type "submit" is the one determined by the browser to act as pressed (which is what the question was about). Then with the other button you can use it as submit button as well using JavaScript events like the onClick event that you have in your example. So my answer is relevant and don't deserve a down vote. Please remove it.
  • Stewart
    Stewart almost 11 years
    multiple submit buttons. The one with type "submit" - you have contradicted yourself there.
  • Stewart
    Stewart almost 11 years
    If your point was to suggest removing the ambiguity by making only one of them type "submit" and using JavaScript to implement the other buttons, then this is a duplicate of graphic's reply and as such has already been dismissed as a bad idea.
  • Jesús Carrera
    Jesús Carrera almost 11 years
    The one with type "submit" + the one with type "button" === multiple buttons. So no contradictions there. And yes, my point was that. But that is a bad idea for you or for JS disabled supporters doesn't mean that is a bad idea for everyone. My app requires JS to work, so it worked for me.
  • graphic
    graphic almost 11 years
    Another method involves styling a copy of the desired submit button so that its absolute position is off-screen, and making sure it's the first button declared on the form, despite its invisibility. It is difficult to validate form entries without JavaScript unless it's done at server end.
  • gcb
    gcb almost 11 years
    @yellowandred what happens? will take a look later
  • Yellow and Red
    Yellow and Red almost 11 years
    my mistake, I changed {type="hidden"} and i didnot notice the same 'name' values.
  • tvanc
    tvanc over 10 years
    You can just set the tabindex attribute of the hidden button to -1
  • Sz.
    Sz. over 10 years
    What's that <input/> up there for?
  • James
    James over 10 years
    @lunakid <input /> is there to show the placement of input-level form elements (textarea, radio, checkboxes, inputs, etc) in relation to the submit buttons.
  • Jamie Kitson
    Jamie Kitson about 10 years
    This doesn't work for me in IE11 or Fx30. The value is always set to the hidden value.
  • Jesús Carrera
    Jesús Carrera about 10 years
    Now that I read the thread again, I understand what you mean. Yes your question is about multiple type="submit" buttons, and my solution leaves only 1 type="submit". Sorry about the confusion, I'll edit my answer.
  • Nick Retallack
    Nick Retallack almost 10 years
    <button>s can still trigger form submit behavior.
  • Pacerier
    Pacerier over 9 years
    Ok, so that's what it's supposed to do. Can I use?
  • Clint Pachl
    Clint Pachl about 9 years
    I'm glad to see "implied submission" in HTML5.
  • Clint Pachl
    Clint Pachl about 9 years
    This does not have the desired behavior in the latest versions of Chrome and Firefox. The "action" parameter always contains the value "login" for implicit submissions. This would be an elegant solution, but cannot be relied upon.
  • gcb
    gcb about 9 years
    @ClintPachl all modern browsers will either send, if you click forgot password on the example: ?action=forgot_password or ?action=login&action=forgot_password it is still workable... though not as elegant as before :(
  • Christoffer Bubach
    Christoffer Bubach over 8 years
    Users with JS disabled won't be able to use the internet, it's as simple as that nowadays.
  • Matt Roy
    Matt Roy about 7 years
    I used keydown instead of keypress (avoid waiting for keyup) and I added e.preventDefault(); into the beginning of this function to avoid execution of the "real" default button. Works really well.
  • Sz.
    Sz. over 6 years
    Ah, OK, I see. :) And that overflow: visible? Is it really needed? (BTW, funny to see how bad fortune swiped me back to web dev. again and now I find myself here after those 4+ years just to continue exactly where we left off! :) So, hi there James, hope you, and all the others, are well! :) )
  • toddmo
    toddmo about 6 years
    Simple and fixes the issue
  • James
    James over 5 years
    Hello again! I haven't tested lately, but at the time of writing: yes. overflow: visible is required because an element needs to be "visible" to the DOM in order to receive user input.
  • rbassett
    rbassett over 5 years
    Very useful first paragraph bracket section - thanks.
  • Peter Mortensen
    Peter Mortensen almost 3 years
    Perhaps update for the current state of affairs?
  • Peter Mortensen
    Peter Mortensen almost 3 years
    The link is broken (404).