views:

456

answers:

5

I'm aware that there are already a bunch of questions about form layout using CSS versus Tables. On the whole, I think CSS is the way to go, but all the CSS solutions I've seen have the drawback of "hard coding" the width of the labels and/or input fields.

The result is that one or two custom rules needs to be added for each form, assuming that the maximum width of the labels are different in each case.

Is there a way that I can style forms, such that it will automagically line up the labels and inputs regardless of how long the labels are?

A: 

There's nothing wrong with having rules for that specific page embedded in the page header, instead of having different files for everything.

If your forms are so different that you say they are, then there's no other way to do it than to make custom rules for each...

Whether or not you want to put all form styles in a huge file, or just include in the page header those that are relevant, depends on how many forms your users will access on an average visit. A few forms per visit; put them in the header. A lot of forms per average visit; put them all in a separate file so it can be cached by the user.

Tor Valamo
+6  A: 

Have a look at the form on the left handside at this URL http://www.blueprintcss.org/tests/parts/forms.html

If you place label on 1 line and the input box on another line then you don't have to worry about the alignment of labels. Style it a bit more you will have a clean and nice web2.0 like form

Cheers

Phradion
+1 for this. If you will have a very long label in one field, a short one in other, then making it to be 2 column will be ugly, even if you use table. Make it 2 line, label in line 1, form field in line 2. You will not need to worry about label length anymore.
Donny Kurnia
None of those layouts are comparable.
Greg
A: 

Well the subject of placing a label above or adjacent to the input is a separate discussion (I recommend reading Luke Wroblewski's book on the subject: http://www.lukew.com/resources/articles/web_forms.html)

Styling web forms is quite trivial. First off you want to ensure you are marking up your forms in a semantically appropriate manner. This is one of the main advantages allowed to you now that you are using CSS for layout instead of tables. For more on this see the excellent List Apart Article on the subject: http://www.alistapart.com/articles/prettyaccessibleforms/

Now in the aforementioned article the author uses a display property called inline-block. This is a rather simple way of achieving the affect. Simply apply:

label {
   display: inline-block;
   width: 120px; /* Specify the width that works for your design */
}

And your labels will have a fixed length with the input adjacent to them. However, if you do not specify the width and just use:

label, input {
   display: inline-block;
}

Then your labels and inputs will both line up inline 'automagically' as you put it. The problem here is not a technical issue but rather a design issue. If you're inputs to not line up vertically then it will make it more difficult for a user to complete your form. This is another consideration you should keep in mind as it's easier to position the label and input in this manner than it is to accommodate for fixed widths.

Another issue is that inline-block doesn't work well in certain browsers. Inline-block is not reliable in older versions of Firefox or IE. So I tend to use an alternative method. Let's say you mark up your forms in a semantically appropriate way using a list. Well in that case you could have something like:

<form>
  <fieldset>
    <legend>Health information:</legend>
    <ul>
      <li><label>Height</label> <input type="text" size="3" /></li>
      <li><label>Weight</label> <input type="text" size="3" /></li>
    </ul>
  </fieldset>
</form>

In this case we can use a fixed width and absolute positioning to line up our elements adjacently:

form li {
  display: block;
  padding: 2px;
  position: relative;
}

/* The top and left position of 2px simulate 
   padding since we are using absolute positioning. */
form label {
  display: block;
  left: 2px;
  position: absolute;
  top: 2px;
  width: 120px;
}

form input {
  display: block;
  margin-left: 125px;
}

The label is positioned relative to the list item and the input is pushed over to the side with a left margin. There is an issue with this method though. This method will only work with a hardcoded width. More importantly, a multiline label won't clear properly. So in this situation we can take a similar approach but use floats and overflow. So we could use this alternative CSS on the same html markup I showed earlier:

form li {
  display: block;
  overflow: hidden; /* This clears the floating element. */
  padding: 2px;
}

form label {
  display: block;
  float: left;
  padding-right: 5px;
}

form input {
  display: block;
}

Now with this method the label is floated to the left of the input. If you do not specify a width the label will be as wide of the contents that reside in it (up to the point of the width of it's parent node in the HTML document). By setting overflow to hidden on the parent object there is no need to clear the element. This technique will work with a hardcoded width or the inherited default which is width: auto.

Last but not least if you want to use the most efficient form approach (labels on top of the inputs), which has proven to be the style of form that users can complete the fastest, the only css you need in order to accomplish this is:

label, input {
  display: block;
}

One other note - with marking up your HTML as such you might be wondering about all of those list elements creating bullet points etc. You should opt for including a CSS reset in your document to ensure consistency amongst browsers. I recommend Eric Meyer's:

http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/

Jim Jeffers
The question specifically asks for solutions where the labels are of arbitrary length. This does not address that concern in any way.
Max Shawabkeh
Ah I see. I will make some edits to correct this.
Jim Jeffers
The methods posted albeit one do what the question asks if you omit the rule for width. I've now explained this in the solution whilst also providing all three popular methods for achieving this style of layout with CSS and HTML. Additionally the answer points considerations the designer should take when designing forms in such a manner. Additionally, it references proper methods for marking up web forms in semantically appropriate HTML as the question mentioned they are transitioning from table based layouts.
Jim Jeffers
"Styling web forms is quite trivial" Given the size of the code posted this doesn't look trivial.
Jay
Yes it is. It's really fairly simple. In this post I've explained four different approaches to do it.
Jim Jeffers
Does any of these solutions offer left alignment of the values without hardcoded widths?
kemp
All of them except the absolute positioning method will do this. You just don't hardcode the width and a floated or inline-block element assume the width their content.
Jim Jeffers
I'm sorry I must be doing something wrong then: I'm trying your markup with your only style rules not involving a label with fixed width, and input boxes are not aligned at all.
kemp
A: 

Personal opinion: use a table.

Every time you write something like

label {
    width: 150px; /* or whatever width */
}

then you are mixing content and presentation because the value of the label can only be calculated if you know what it will contain, which goes against the principles of the semantic-CSS purists.

kemp
That is completely incorrect. When you use a table you are mixing content with presentation. The entire reason we have CSS is to separate this. Hence the layout is controlled by specifying the width in the CSS file. If you use a table. The layout is controlled by the table element now embedded in your content.
Jim Jeffers
I didn't say it isn't so. I said that *even* with a styled label tag you're mixing content with presentation. CSS definitions should not depend on what a field contains, but they do in this case. So you just might as well use a table which works reliably in all browsers, does what the OP wants and just in a few lines of code. Tables could be abandoned if CSS offered alternatives for *all* needs working in all browsers without silly hacks.
kemp
A: 

You can handle this by floating the labels and placing them in a floating block element, and similarly for the input fields. This will create a two column layout that automatically resizes based on the contents. Here's the HTML:

<form>
    <div id='labels'>
        <div>Name: </div>
        <div>Street:</div>
        <div>This is a longer than usual label:</div>
        <div>City:</div>
    </div>

    <div id='inputs'>
        <div><input type="text"></div>
        <div><input type="text"></div>
        <div><input type="text"></div>
        <div><input type="text"></div>
    </div>

</form>

And here are the CSS rules:

#labels {
    float: left;
}

#labels div {
    clear: left;
    float: left;
}

#inputs {
    float: left;
}

#inputs div {
    clear: left;
    float: left;
}

#labels div, #inputs div {
    height: 30px;
}

EDIT: If you want to create a semantic connection between labels and inputs, you can formally tag each label as an html label and then use the for and id attributes to link them. For example, here's a label definition:

<div><label for='name'>Name: </div>

and here is the corresponding input field:

<div><input id='name' type="text"></div>
jdigital
+1: A bit verbose, but works like a charm!
Max Shawabkeh
I'm sorry but this doesn't keep any connection between labels and their values. They are in completely separated divs and their only link is visual if you happen to place them side by side. There is no "semantic" connection and the meaning of your content stricly depends on its presentation. Aligning them is trivial, the point is align them in a meaningful way.
kemp
This is easily solved, and I've edited the answer accordingly.
jdigital
This is a small nitpick, but the baseline of the label and the inputs do not line up in ie6.
Greg