views:

415

answers:

7

I want to display an HTML form containing labelled text fields, like this:

      First Name:  [_____________]
       Last Name:  [_____________]
   Date of Birth:  [________]

My obvious approach is to use a <TABLE> and simply place the labels and text fields in its cells, but is there a better way, e.g. a CSS-based approach?

EDIT:

  1. I'm looking for a way that reduces the verbosity in the HTML file.
  2. And yes, I'm looking for auto-sizing of the labels. See a related question about wrapping labels
+2  A: 

Use a CSS framework like Blueprint and use that to style the forms.

Another trick would be to create virual "columns" with css and float them next to each other. Labels in one column and inputs in another. Put that (both columns) in a div with a large enough width and float the columns the opposite way you want to align them.

Here's some code (because I am creating a form) that will work for basic forms. The only constraint is the large right margin on inputs.

form input, form select
{
    float: right;
    margin-right: 650px;
}
form label
{
    float: right;
    margin-top: 5px;
    margin-right: 10px;
}
form .nofloat
{
    float: none;
    margin: 0;
}
form br
{
    clear: both;
}

And layout like so

<input type="text" id="name" />
<label for="name">Name</label>
<br />

On top of this small, narrowly written code, there is an entire article related to creating tableless forms in CSS.

Josh K
The last time I looked at Blueprint (about a year ago), it didn't render correctly on all popular browsers and involved far too many hacks and convolutions.
T.J. Crowder
Two columns is worse for accessibility than the table, which at least keeps them in logical reading order.
bobince
@Bob: And a table is for tables of information. It's not the correct use.
Josh K
One could very much argue that it is in fact a table of information
kemp
@Kemp: It's not. It's for *input*, not presenting rows and columns of *data*.
Josh K
Well, input or output it's data anyway. A spreadsheet table has a lot if *input* cells, and it's still a table, isn't it.
kemp
@Kemp: No, it's not. That is a free forming spread sheet. Forms aren't.
Josh K
Well can't say much against "no it's not" kind of arguments.
kemp
+17  A: 
T.J. Crowder
[Blueprint](http://blueprintcss.org) – As mentioned in my answer.
Josh K
+1 - The down-voting is silly for a correct answer.
Kyle Rozendo
I would upvote this answer, but I just hate this "oh, downvote me you senseless clods" bullshit. Especially repeated twice.
doublep
@doublep It works brilliantly on reddit -- guaranteed upvotes to any post that leads off with "I know I'll get downvoted, but". It's like people read it and think "Oh yeah? OH YEAH?! *upvote* TAKE THAT!"
Michael Mrozek
@doublep: Not intended that way, but I understand how you could read it that way. (No call for swearing, though.) But for clarity: I do **not** think anyone who wants to downvote this is a clod.
T.J. Crowder
@Michael Mrozek: [offtopic] I know. I developed a rule to never upvote anything "calling" for a downvote, not even when I strongly like it, after seeing this infestation on reddit.
doublep
@doublep and the three (so far!) upvoters on his comment: I've never been on reddit (yes, really) and haven't seen this behavior on SO. I've removed the comments that you took exception to, thanks for letting me know.
T.J. Crowder
@Josh: I've looked at Blueprint, and with respect, it fails horribly on the "hacks" front. And the complication front.
T.J. Crowder
@T.J.: It's a matter of principle. Tables are **not** for layout. **Ever**.
Josh K
@Josh: Well, we just disagree there. :-) And fair enough.
T.J. Crowder
+1 for the answer. Missing link: http://giveupandusetables.com/
Tomalak
@T.J, I removed my down vote by the way. ;)
Josh K
@Josh: Thanks for that! Good of you. :-)
T.J. Crowder
+1 for me. The point of the CSS push was not to get rid of all `<table/>` s, it was to stop using `<table/>` s to render non-tabular layouts. But if you are actually rendering a table... use a `<table/>`! It's the semantically correct choice.
roufamatic
@Josh K: sometimes when desired results meets principle, desired result wins
kemp
@kemp: I *refuse* to believe that there is a situation where that's the case.
Josh K
As much as I agree on the base principle, I just think that blind absolutism is futile. Fact is that no alternative solution offers *everything* you can do with a table in this case. You could go for a compromise and sacrifice something, but sometimes you're just paid to do what you're told.
kemp
@Josh: You're right, tables aren't for layout. Except that using tables for forms is perfectly semantic, since forms are tabular data. And as a general point, the term "pure CSS" makes me want to pull my hair out. By definition, a pure CSS website is a nonexistent concept.
DisgruntledGoat
@Disgr: Forms are not tabular data. Layout and styles is what's meant by "pure CSS," not that tables are forbidden.
Josh K
@Josh: Not to drag this out (esp. since I originally agreed that this was not a semantic use of tables), but Goat and roufamatic have an interesting point. If I had a series of rows where the `th` contained (say) "First name:" and the following `td` contained "Sam", the next row's `th` was "Last name:" and was followed by `td` = "Samson", that would be tablular data. So why is it not tabular data if the "Sam" and "Samson" are fields? It's an interesting question...
T.J. Crowder
+10  A: 

In terms of usability and if vertical space is not a limiting factor, a list of fields with the label above each field is the quickest to read and fill out, and can be done aesthetically. See many of the usability studies on the web for more info, eg. http://www.lukew.com/resources/articles/web_forms.html

jball
+1 for LukeW, but I'd like to keep labels right-aligned to the left, one of the practices his study advocates for casual users.
Jen
+1 I'm a big fan of these when you can do them, not (only) for semantic markup reasons, but for aesthetic reasons. They just look good.
T.J. Crowder
+1 for referencing "usability studies" on a question where I'd have expected the focus to be on the table-layouts holy war
LeguRi
+3  A: 

I think something like this is what i do but also won't autosize to the length of the text but it's cleaner in my opinion

<form>
  <label for="firstName">First Name</label>
  <input type="textfield" name="firstName" />

  <label for="lastName">Last Name</label>
  <input type="textfield" name="lastName" />
</form>

label {
  float:left;
  width:30px;
}

input {
  float:left;
  margin-left:30px;
}
Catfish
Fixed width means your presentation depends on the content
kemp
+3  A: 

The article is a bit old, but I've always found a list apart's advice to be solid: (if you do want to get rid of your tables)

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

quoo
+1 good article, but requires fixed-width labels
Jen
Oh, oops, I missed the part about fixed width labels...
quoo
+7  A: 

I'd like to use definition lists (<dl>) they tends to be semantically correct. A label is defined by an user input. It has sense to me. <dl> expresses semantic contents more accurately than a table.

<dl>
    <dt><label for="name>Name</label></dt>
    <dd><input type="text" id="name" /></dd>

    <dt><label for="email>Email</label></dt>
    <dd><input type="text" id="email" /></dd>
</dl>

Here is an example

By the way they degrade gracefully in all browser, even text-based.

Boris Guéry
this technique never occurred to me... this does seem to be semantically correct, simple, and actually works across browsers... succeeding at all three of those categories makes it the correct answer, IMHO. +1
rmeador
It's an interesting approach. I don't think I'm with you semantically, but it's a matter of opinion. Sadly, it still has the problem that all of the CSS solutions I know have has: The labels won't auto-size, which the OP says she wants. You have to explicitly give them a size (in your "worked example", 33% of 50% of the browser width).
T.J. Crowder
Doesn't applying a `display: inline-block` do the trick for auto-sizing ?
Boris Guéry
@Boris: No, I'm afraid that doesn't help. What makes it mostly *seem* to work is the `width:33%`, not the `display: inline-block` (although you do also need that with `dt`s for this). That means that the `dt`s will all be *at least* 33% of the container, but a long label would be longer, resulting in a staggered look. Perhaps not a big deal when you've made the labels so big (~17% of the width of the browser window), but you don't usually have that much room to work with.
T.J. Crowder
+1  A: 

Typically, I have found that there are at least some issues when not using Tables for forms. The general things I have not been able to solve:

  • Background-color for fields/inputs is not really possible without a faux background
  • Auto-sizing columns, but I think this is OK
  • Field hover with CSS, you could use JS but Tables can do this with pure CSS

I might be missing a few things, but the most flexible mark-up if you are using CSS is as below:

<div class='form-field'>
   <label>Name</label>
   <input />
</div>

You have issues if you want multiple fields per label section, so you have to introduce another div to hold the inputs (to allow the label to still float left etc):

<div class='form-field'>
   <label>Name</label>

   <div class='form-inputs'>
      <input />
      <input />
   </div>
</div>

With the above mark-up you can achieve very flexible forms, I won't post the CSS as it's very similar to a 2 Column-Layout.

I still need to sit down and try and figure out if pure CSS forms are viable for all occasions but tbh it's very unlikely!

Forms are the worst thing to style using CSS. The only major Cross Browser problems i've had are when styling the FieldSet and Legend elements. No real hacks, but they take some work to look good.

MiG
How will this align the labels?
Jen
You would float the label left, set its display to inline-block, then add a fixed width. The preferably needs a class on it to make it easier to target with CSS, but the minimum for that class is a left margin equal to the width of the label. The 'form-field' class would have overflow:hidden set to ensure floats are cleared, and the form-inputs would change it slightly for multiple fields.Cheers
MiG