views:

369

answers:

5

I have a wizard-style HTML form with a row of submit buttons for the Back/Next/Cancel actions (in that order). The form can also contain a varying number of input fields, such as text fields, radio buttons, checkboxes, dropdowns (select tags), and textareas. The customer requires the "Next" button to be the default action, so that if the user types into a text field and presses Enter, it should submit the form as if they had clicked the "Next" button.

The problem is that in this scenario, the browser (at least IE, which is what 99% of our customers use) submits the form using the first button declared in the form, which as you can see from the above list is "Back", not "Next" as desired.

One fix I read about is to declare the Back and Next buttons in reverse order (i.e. Next first) then use CSS to display them around the right way, like so:

<html>
  <head>
    <style type="text/css">
      .formSubmitButtons {
        direction: rtl;
        float: left;
      }
      .formSubmitButtons input {
        direction: ltr;
        float: none;
      }
    </style>
  </head>
  <body>
    <form action="blah" method="POST" enctype="application/x-www-form-urlencoded">
      <div class="formSubmitButtons">
        <input type="submit" name="btnNext" value="Next">
        <input type="submit" name="btnBack" value="Back">
      </div>
      <input type="submit" name="btnCancel" value="Cancel">
      <br/>Some text fields go here...
    </form>
  </body>
</html>

This provides the desired behaviour and button order in both Firefox and IE, however the spacing of the Cancel button relative to the others is inconsistent. In IE6 it looks nice enough, but in Firefox 3.0.5, the Cancel button is jammed up against the Next button.

Does anyone know what CSS magic I need to weave in order to get these three buttons to space evenly in both browsers?

(avoiding the issue by sorting the buttons Next/Back/Cancel is not an option)

(also thanks to everyone who suggested JavaScript-based solutions, but not all our customers allow JS, so it has to be a straight HTML and/or CSS solution)

Here's what I ended up doing that worked nicely (based on Cletus's suggestion):

<!--
<input type="submit" name="btnNext" style="position: absolute; left: -9999px" tabindex="-1">
<input type="submit" name="btnBack" value="Back">
<input type="submit" name="btnNext" value="Next">
<input type="submit" name="btnCancel" value="Cancel">
-->

(ignore the wrapping comment tags, they're just so you can see the HTML)

+1  A: 

Have you considered using this trick? Basically you just have a hidden button appear first which does the desired action.

cletus
I tried something like that, but I'll give it another go and let you know. In the meantime if anyone can make my original approach consistently look nice, that would be welcomed too.
Andrew Swan
That trick works, but acts in a way that will confuse some users. In IE, when you click into a text field, a black border appears around the first visible button (Back), but when you press Enter, the hidden Next button takes effect. So it looks like pressing Enter will go Back, but it goes Next.
Andrew Swan
Although that trick didn't work as-is, it led me in the right direction, so that's good enough for me to make yours the accepted answer. I'll add the full details of what I did to the question.
Andrew Swan
A: 

Could you just define a style

.btnMargin {
    margin-left:5px;
    margin-right:5px;
}

And just apply it to the buttons

<input type="submit" name="btnNext" class="btnMargin" value="Next">
<input type="submit" name="btnBack" class="btnMargin" value="Back">
...
<input type="submit" name="btnCancel" class="btnMargin" value="Cancel">

?

If you have the same style to all, it seems to yield in a few pixel differences between Next/Back and Back/Cancel. If it's crucial that this wouldn't happen, you could define individual margins to buttons. ?

Jaanus
I fiddled with various margin settings, but couldn't get it to work nicely in both browsers.
Andrew Swan
A: 

This plasces the buttons in the back, next, cancel order, right next to each other. The only drawback is that you have to set a apecific width on the first button container to make it work in IE7. It works fine without that in Firefox and IE8.

The doctype is important so that the page is rendered in standards compliant mode. Without it the page displays in quirks mode which makes IE display the form elements with completely different spacing.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;
<html>
<head>
<style type="text/css">
    .formButtons { float: left;  }
    .formSubmitButtons { width: 120px; }
    .formSubmitButtons input { float: right; }
    .formFields { clear: both; }
</style>
</head>
<body>
    <form action="blah" method="POST" enctype="application/x-www-form-urlencoded">
    <div class="formButtons formSubmitButtons">
     <input type="submit" name="btnNext" value="Next">
     <input type="submit" name="btnBack" value="Back">
    </div>
    <div class="formButtons">
     <input type="submit" name="btnCancel" value="Cancel">
    </div>
    <div  class="formFields">
     Some text fields go here...
    </div>
    </form>
</body>
</html>
Guffa
Sadly this approach is vulnerable to a problem that you couldn't have known about, namely that because the text of all buttons is localised and therefore of arbitrary length, you can't use absolute pixel sizes for anything.
Andrew Swan
A: 

Make the buttons type="button" instead of type="submit". Then, add a hidden field, e.g.:

<hidden name="continue" value="Next"/>

Finally, add javascript onclick handlers to the buttons, which first set the value of the hidden field to the name of the pressed button, and then submit the form.

David Hanak
Thanks for the suggestion David, but JS is not an option; I've updated the question to reflect this.
Andrew Swan
A: 

Why do you not just float the Cancel button right?

If it is only a firefox problem you could use an attribute selector like this input[name="btnCancel"] {float: right;} or margin-left or whatever you want. Otherwise just use classes on the inputs.