views:

1114

answers:

11

I've gotten used to using <table>s for aligning my form fields perfectly. This is how I commonly write my forms:

<table border="0">
   <tr>
     <td><label for="f_name">First name:</label></td>
     <td><input type='text' id='f_name' name='f_name' /></td>
     <td class='error'><?=form_error('f_name');?></td>
   </tr>
</table>

I know this is bad practice, and I want to use css, <label>s, <div>s, or a cleaner method. However, the fact is, <table>s work extremely well for the forms. Everything is aligned exactly right, the spacing is perfect, all errors exactly below each other, etc.

I recently tried using <dt> and <dd> tags for a form, but I ended up reverting back to tables just because they looked so much better.

Is there any hope for people like me, or are tables just the best way to create forms?

+3  A: 

Why do you not want to use tables? It sounds like they are working perfectly for you now. Are you worried about accessibility issues? Just because it is a table doesn't mean that accessibility will suffer.

I want to caution you from creating a new solution to a solved problem for nothing other than purity's sake. Even if you are worried about semantics, what kind of semantics describe a form anyway?

Andrew Hare
I'm concerned about semantics basically :) It would just be more elegant to use a better solution. Tables are meant for tabular data, etc...
Click Upvote
I agree - semantics are very important for *content*. My point is that a form is not real content anyway and there are not really any semantics to describe it.
Andrew Hare
"a form is not real content anyway" WTF
annakata
Semantics are ways of describing content in a document - how much semantic value is lost by laying out a form in a table as opposed to using block-level elements? A form contains no content until the user enters it - what is the semantic value of an empty form?
Andrew Hare
This is *really* wildly off base: the whole point about semantic mark-up is that the structure *itself* is content. A form without user input has plenty of content, every single field is meaningful. Have you ever tried using a screen-reader yourself? It's an illuminating experience.
annakata
+11  A: 

Yes, use labels and CSS:

<label class='FBLabel' for="FName">First Name</label>
<input value="something" name="FName" type="text" class='FBInput'>
<br>

css:

.FBLabel, .FBInput {
    display:block;
    width:150px;
    float:left;
    margin-bottom:10px;
}

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

Diodeus
This would break with a long dropdown, a long textarea, or error messages won't show up aligned correctly
Click Upvote
Those issues are easy enough to work around. This is just the foundation you would start with.
Dave Ward
+2  A: 

Really depends on who you talk to. The purists say use CSS because the table element was not meant for layout. But for me, if it works, why change it? I do use CSS now for layout, but I still have plenty of legacy code I have not and will not change.

Ziltoid
I really really wish this attitude of "ain't broke not fixin" wasn't so prevalent on SO
annakata
+6  A: 

A List Apart has a good article about this kind of thing. It's not as simple as you'd hope but I've found the extra work is worth it given how much cleaner your forms will be.

Mr Grieves
+3  A: 

I use the following method most of the time and it allows me to get all my alignment set up exactly how I like it. As you can see, it gives me a great number of hooks for CSS and JS.

<form id="login-form" action="#" method="post">
    <fieldset>
     <label id="for-email" for="email">
      <span class="label-title">Email Address <em class="required">*</em></span>
      <input id="email" name="email" type="text" class="text-input" />
     </label>

     <label id="for-password" for="password">
      <span class="label-title">Password <em class="required">*</em></span>
      <input id="password" name="password" type="password" class="text-input" />
     </label>
    </fieldset>

    <ul class="form-buttons">
     <li><input type="submit" value="Log In" /></li>
    </ul>
</form><!-- /#login-form -->
Mark Hurd
Why put the input inside its own label?
Click Upvote
this is a little redundant. labels can either surround the input or refer it with the for="xx" attribute. Mark is doing both.
Javier
A few reasons - bigger click target, and gives you more flexibility over spacing/styling as you can target individual labels OR their contained inputs directly. I keep the "for" attribute in place so the markup validates.
Mark Hurd
A: 

I have used this in the past fairly effectively:

HTML:

<fieldset>
  <p>
    <label for="myTextBox">Name</label>
    <span class="field"><input type="text" name="myTextBox" id="myTextBox" /></span>
    <span class="error">This a message place</span>
  </p>
</fieldset>

CSS:

<style type="text/css">
fieldset label, fieldset .field, fieldset .error { display: -moz-inline-box; display: inline-block; zoom: 1; vertical-align: top; }
fieldset p { margin: .5em 0; }
fieldset label { width: 10em;  text-align: right; line-height: 1.1; }
fieldset .field { width: 20em; }
</style>

The only really gotcha is Firefox 2 which gracefully degrades. (see the -moz-inline-box which is a bit of hack, but not too bad)

Josh
+2  A: 

There are tons of ways out there to do it without tables. Once you get the basic format down it's as easy to work with as tables are, it's just the initial playing around that can be a pain. So, just look to others that have already done the work of figuring it all out for you:

I also documented the method I've settled on last week (a snippet):

<form action="/signup" method="post">
<fieldset>
<legend>Basic Information</legend>
<ol>
<li><label for="name">Name <span class="error">*</span>
    </label><input type="text" id="name" name="name" size="30" /></li>
<li><label for="dob">Date of Birth <span class="error">*</span></label>
    <div class="inputWrapper">
    <input type="text" id="dob" name="dob" size="10" />
    <span class="note">YYYY-MM-DD</span></div></li>
<li><label for="gender">Gender <span class="error">*</span></label>
    <select id="gender" name="gender">
    <option value=""></option>
    <option value="female">Female</option>
    <option value="male">Male</option>
    </select></li>
</ol>
</fieldset>
</form>

And the CSS:

fieldset { 
    margin: 0 0 20px 0; } 

fieldset legend { 
    font-weight: bold; 
    font-size: 16px; 
    padding: 0 0 10px 0; 
    color: #214062; } 

fieldset label { 
    width: 170px; 
    float: left; 
    margin-right:10px; 
    vertical-align: top; } 

fieldset ol { 
    list-style:none; 
    margin: 0;
    padding: 0;} 

fieldset ol li { 
    float:left; 
    width:100%; 
    padding-bottom:7px; 
    padding-left: 0; 
    margin-left: 0; } 

fieldset ol li input, 
fieldset ol li select, 
fieldset ol li textarea { 
    margin-bottom: 5px; } 

form fieldset div.inputWrapper { 
    margin-left: 180px; } 

.note { 
    font-size: 0.9em; color: #666; }

.error{ 
    color: #d00; }
Parrots
A: 

There's no one-size-fits-all for this. The table example you used can be improved on, though:

<table>
  <tbody>
    <tr>
      <th scope="row"><label for="f_name">First name:</label></th>
      <td>
        <input type='text' id='f_name' name='f_name' />
        <?php form_error('f_name'); ?>
      </td>
    </tr>
    <!-- ... -->
  </tbody>
</table>

Not too sure about the error part; I think it makes more sense putting it next to the input than having a separate column for it.

Ant P.
+2  A: 

The answers above are all very fine and there are indeed nice ways of laying out tables using css, however it becomes very difficult when you have a form with multiple columns.

I have really struggled, and that is probably a reflection on me not the capabilities of CSS, to come up with good looking layouts for multiple column forms without resorting to tables.

Steve Weet
+6  A: 
Gavin Miller
+5  A: 

If you don't use tables you need to know the width of your labels upfront. This can often be a problem for multi-language sites (i18n).

With tables, they stretch to fit labels of differing sizes. CSS alone can't do that yet in a well-supported way.

Damo
+1. This is my problem with CSS based approaches. I can't justify the cost of CSS to my clients.
David