views:

1731

answers:

9

For future reference here is the final result with pixel perfect precision:

fluid CSS form

The CSS code:

._25 {
    width: 21%;
    display: inline;
    float: left;
    margin-left: 2%;
    margin-right: 2%;
}
._50 {
    width: 46%;
    display: inline;
    float: left;
    margin-left: 2%;
    margin-right: 2%;
}
._75 {
    width: 71%;
    display: inline;
    float: left;
    margin-left: 2%;
    margin-right: 2%;
}
._100 {
    width: 96%;
    display: inline;
    float: left;
    margin-left: 2%;
    margin-right: 2%;
}
label {
    width: 100%;
}
input {
    border: 1px solid #B3B3B3;
    width: 100%;
    -moz-border-radius: 3px;
}
textarea {
    border: 1px solid #B3B3B3;
    width: 100%;
    -moz-border-radius: 3px;
}
select {
    border: 1px solid #B3B3B3;
    width: 100%;
    -moz-border-radius: 3px;
}

And some sample HTML code:

<div class="_50">
    <p><label for="in_user">Username</label><input id="in_user" type="text" value=""/></p>
</div>

<div class="_50">
    <p><label for="in_pass">Password</label><input id="in_pass" type="text" value=""/></p>
</div>


Recently I've started using CSS grid systems and I find the whole process of designing a webpage much more simpler. Now I'm trying to stylize form elements but I'm having a really hard time making forms with columns, take the following example:

  • div (width = 400px)
    • form
      • ul
        • li .half
          • label
          • input (should be 200px wide)
        • li .half
          • another label
          • another input (should also be 200px wide)

Basically I'm applying a class that has a width attribute of 50% but putting both inputs side by side makes the row to be bigger than 100% (400px) - I guess this is because of borders, margins and paddings.

mockup of what I'm trying to achieve

Is there any CSS grid system that I can use to have multi-column forms while still making all the form elements have the same size (inputs, selects and textareas); eg. 1 input in 1 column should have 400px while 2 columns should have 200px each.

EDIT: Wufoo has some examples of what I'm trying to do but I'm too ignorant at CSS to understand all that code and I would appreciate if someone could give me some pointers.

+5  A: 

check this out : http://www.noupe.com/design/ultimate-guide-to-grid-based-web-design.html

there is everything you need to know, including css api and templates

EDIT : here's my final solution with fluid960 css template

And here's a graphical example. Of course, you can easily change the colors by editing the css.

Maxime ARNSTAMM
I don't see how it applies to forms..
Alix Axel
it applies for everythingthere is, for instance, a css template called fluid960 and it has an livedemo here : http://designinfluences.com/fluid960gs/16/fluid/none/see how the forms are done
Maxime ARNSTAMM
Sorry, the carriage return was skipped. I was saying : "It applies for everything. There is, ...".
Maxime ARNSTAMM
But then again, **fluid960 doesn't use multi-collumns in forms** and I also don't understand (in the second form) why input's have a width of 98% and select's have a width of 99%.
Alix Axel
For the multicolumn form, i think you could put some <div class="grid_x"> into your main div and in each, you arrange your fields..For the widths, try, with firebug, to change the width of input and select to 100% : they won't have the same width and they will not be aligned with the container. I don't know why precisely, that's part of the rendering i guess.
Maxime ARNSTAMM
@Eligriv: That sucks, I suppose multi browser compatibility is out of the question then. But then again, Wufoo seems to do it right.
Alix Axel
Here's your form with 960grid css template : http://pastebin.com/m3d0312d3you just have to find out how to fluidify your textarea and your good.
Maxime ARNSTAMM
Doesn't seem to work right for me: http://i46.tinypic.com/25hlf95.jpg
Alix Axel
it is because of the textarea : the width is fixed, and i don't know how to make it fluid (width in %). Or you lower the number of columns in the source (i put 71 because i was in fullscreen)
Maxime ARNSTAMM
@Eligriv: is it really? what about the email and country fields? They look kinda trimmed for me.
Alix Axel
The example in your edit seems to work just fine now, thanks a bunch. =)
Alix Axel
Changing the width of the inputs from 98% to 100% and the width of the selects from 99% to 100% makes it really nice, I believe it's pixel perfect. I was just wondering if this solution only works with the fluid960 grid or if it'll work with the fixed 960 grid system.
Alix Axel
+2  A: 

I think this is what you are looking for:

http://www.alistapart.com/articles/prettyaccessibleforms/

It should help simplify your structure a little bit. It doesn't explicitly describe how to make multiple column forms, but the technique could probably expand to that with some creativity on your part.

Nate B
"...with some creativity on your part" that is exaclty the part I'm having trouble with. =|
Alix Axel
Well, off the top of my head (I've not attempted this), I would imagine you could use the method in the article (fieldsets enclosing a system of lists, labels, and fields), but enclose the entire thing in a left-floated, fixed-width div. Then, create another and float that one too, in order to have two columns.
Nate B
+2  A: 

No need for the fluid 960 system here, unless you want the form to expand and contract with the browser.

I would recommend the regular old 960 grid system for this. 960 width is great for grids because it divides evenly by 12 and 16 which allows you to set up pixel perfect three and four column layouts.

The best way to get familiar with the 960 grid system is to look at the souce css and the source of the html demo

<div class="grid_6">
     <p>
      contact form
     </p>
    </div>

<div class="grid_3">
     <p>
      name
     </p>
    </div>
Gideon
Sorry but -1. I have no problem with the grid system (960 or blueprint or whatever), what I'm having trouble with is multi-collumns forms and to that purpose 960.gs doesn't help even a bit.
Alix Axel
Sure it will. Create your forms with <div class="grid_6"> and then subdivide the columns with "grid_2" classes. I've done it in the past and it was quite easy.
David Robbins
Check Eligriv's answer and respective comments please, I can't seem to get it working.
Alix Axel
You don't need percentages for this, grid_6 means 6 columns (out of 12) and grid_3 means 3 columns (out of 12). This should solve your problem. Make sure to set display: inline; instead of display:block;
Gideon
+4  A: 

Something like this may help. This is how I did it on a form. It will take some fine tuning though to make it work at your desired width. This might help you get started though.

The CSS:

.contact ul {margin:0; padding:0; list-style:none;}
.contact li {margin-bottom:10px; overflow:hidden;}
.contact label {display:block; margin-bottom:2px;}
.contact label span {color:#999;}
.contact .input {width:592px; border:1px solid #E0E0E0; background:#F6F6F6;}
.contact select.input {border:1px solid #E0E0E0; background:#F6F6F6;}
.contact .third {float:left; width:193px; margin-right:10px;}
.contact .third .input {width:185px;}
.contact .half {float:left; width:294px; margin-right:10px;}
.contact .half .input {width:286px;}
.contact .half select.input {width:294px;}
.contact .omega {margin-right:0;}

The HTML:

<form action="/contact-us" method="post" class="contact">
 <ul>
  <li>
   <div class="half">
    <label for="name">Name:</label>
    <input type="text" id="name" name="name" class="input" />
   </div>
  </li>
  <li>
   <label for="address">Address:</label>
   <input type="text" id="address" name="address" class="input" />
  </li>
  <li>
   <div class="third">
    <label for="city">City:</label>
    <input type="text" id="city" name="city" class="input" />
   </div>
   <div class="third">
    <label for="state">State:</label>
    <input type="text" id="state" name="state" class="input" />
   </div>
   <div class="third omega">
    <label for="zip">Zip:</label>
    <input type="text" id="zip" name="zip" class="input" />
   </div>
  </li>
 </ul>
</form>
Corey
+1 this is the best answer related to my question so far, any idea in how I can use relative widths specified in % instead of fixed widths specified in px?
Alix Axel
well I don't think there is a pixel perfect solution w/out maybe using javascript. Because borders, paddings, and margins are usually pixels, its impossible (as far as I know, and w/out adding too much extra markup) to use percent widths on the inputs and still get that grid perfect.I got pretty close with this though: http://pastebin.com/f15322f08
Corey
Are you sure you need a fluid form? Go for widths in px for forms. Align then in the center (of a screen). Forms that can chenge their size is good but it doesn't worth it to spend too much time to develop.
NilColor
Why isn't Address in a <div>?
MattMcKnight
@Corey: "I don't think there is a pixel perfect solution w/out maybe using javascript" so you're saying that there is a solution using Javascript? Which one?
Alix Axel
@MattMcKnight: address isn't in a div because it's a full length input field. the divs are there to divide the area w/out worrying about margins and paddings.@eyze: it wouldn't be easy. you'd basically have to get the computed widths of the area and all the inputs and make it all fit together. b/c you can't do `input {width:100% - 10px;}` with CSS. but you could figure it out with javascript.
Corey
+1  A: 

I had to do something similar and ended up setting my half-columns to 46%. It leaves an extra bit of room for the padding and gets all your input fields consistently sized.

Ax
I suppose the full-columns aren't 92% in width then?
Alix Axel
The full columns are 96%.
Ax
+3  A: 

First off, do not use a table. Putting form elements in a table does not solve your problem and complicates your maintenance. Using tables to supplement form presentation is a sign of incompetence and complexity. It is also entirely non-semantic. Instead you might actually have to write some CSS. Honestly, if you are going to use tables for non-tabular data then don't even bother using CSS as that multiplies the complexity of maintenance.

Here are some things to keep in mind:

1) Define all your units in "em" units. Most form elements are intended to contain text. Those elements, like text fields and textarea blocks, can be increased and decreased as a feature of accessibility. This means your pixel perfect pretty CSS grid will break the moment a user changes text size on the page.

2) Don't wrap your form element in a div. Like a div, your form is a block level element. Unless the form has peer nodes under a div parent simply direct any presentation directly to the form element and not a parent element that exists only to contain the form.

3) Group your form elements. If you are floating text fields things can get all messed up if the forms are floated independently of their respective label elements. It will be easier to put an ordered list inside your form and then wrap each form element in a list item. This way you only have to worry about defining layout of the label element relative to its form control and then layout of them together by defining presentation of the list item. This method is also semantic and informs text readers of an order upon your form controls.

4) Don't use the !important declaration. This makes for a quick fix in your CSS but completely screws up inheritance and absolutely complicates maintenance. Instead take the extra time to write your code correctly the first time, so that future maintenance is a quick and minor event.

5) Don't use position absolute, unless you really know what you are doing, even if your form is set to position relative. Position absolute results in unexpected behaviors in many cases and unexpected problems.

6) To ensure your CSS code actually defines a true grid use the Firefox MeasureIt plug in. It will help you achieve stunning accuracy and save you incredible time when making your grid.

7) Do everything correctly the first time using as little code as necessary to get the job complete and present your form perfectly. Only then test your form for cross browser accuracy. Make one correction for cross browser accuracy at a time to limit unnecessary bloating to your CSS code.

+1  A: 

Here's a basic kickoff example which may be of use:

<!doctype html>
<html lang="en">
    <head>
        <style>
            fieldset { width: 400px; padding: 1%; }
            input[type=text], select, textarea { width: 98%; }
            .half { float: left; width: 48%; padding: 1%; }
            .full { clear: both; width: 98%; padding: 1%; }
            .right { text-align: right; }
        </style>
    </head>
    <body>
        <fieldset>
            <legend>Contact form</legend>
            <form>
                <div class="half">
                    <label for="name">Name</label>
                    <input type="text" id="name" name="name">
                </div>
                <div class="half">
                    <label for="email">Email</label>
                    <input type="text" id="email" name="email">
                </div>
                <div class="half">
                    <label for="zip">Zip / Postal code</label>
                    <input type="text" id="zip" name="zip">
                </div>
                <div class="half">
                    <label for="country">Country</label>
                    <select id="country" name="country"><option></option></select>
                </div>
                <div class="full">
                    <label for="message">Message</label>
                    <textarea id="message" name="message"></textarea>
                </div>
                <div class="half">
                    <input type="checkbox" id="copy" name="copy">
                    <label for="copy">Send me a copy</label>
                </div>
                <div class="half right">
                    <input type="submit" value="send">
                </div>
            </form>
        </fieldset>
    </body>
</html>

Note that I am using left-floated div's of half-width instead of unordered list items.

As you insist in using percentages, don't expect it to be pixelperfect in all browsers. If you want to have it all pixelperfect, you really need to use pixels.

BalusC
Thanks, I'll try it out. PS: Is this HTML 5?
Alix Axel
HTML5 doctype, yes. But no HTML5-specific elements. It just triggers the standards mode like HTML4 strict does. Also see hsivonen.iki.fi/doctype
BalusC
+1  A: 

One answer is Blueprint. I have read where you don't think it's the answer, but it's still the way I would do it. All the ease of tables with all the power of CSS.

With blueprint the math is pretty easy. Let's say your form spans 10 columns.

<div id="contact-form" class="span-10">
  <h3>Contact Form</h3>
  <form action="contact">
  <div id="form-sec-1" class="span-5">
     <label>Name</label> <br/>
     <input type="text" name="name" /> <br/>
     <label>ZIP code</label> <br/>
     <input type="text" name="zipcode" />
  </div>
  <div id="form-sec-2" class="span-5 last">
     <label>Email</label> <br/>
     <input type="text" name="email" /> <br/>
     <label>Country</label> <br/>
     <input type="text" name="country" />
  </div>
  <div id="form-sec-3" class="span-10 last">
     <label>Message</label> <br/>
     <textarea name="message" />
  </div>
  <div id="form-sec-4" class="span-8">
    <input type="checkbox" name="copy"/>
    <label>Send me a copy</label>
  </div>
  <div id="form-sec-5" class="span-2">
     <input type="submit"/>
  </div>
  </form>
</div>
MattMcKnight