views:

1023

answers:

5

[Meta-note:] I was browsing the question page, getting really tired of "DIVS vs Tables" "When to use tables vs DIVS" "Are Divs better than Tables" "Tables versus CSS" and all the questions that ask THE SAME THING OMG PEOPLE but I would like to see all the ways people tackle the translation of the canonical example of "why you should give up and use tables":

<table>
  <tr>
    <td> Name </td>
    <td> <input> </td>
  </tr>
  <tr>
    <td> Social Security Number </td>
    <td> <input> </td>
  </tr>
</table>

Question: How to best (semantically, simply, robustly, fluidly, portably) implement the above without tables. For starters, I guess a naive implementation uses a fixed column width for the first column, but that can have iffy results for dynamically generated content. Including strengths/weaknesses of your approach in the answer would be nice.

P.S. Another one I wonder about a lot is vertical centering but the hack for that is covered pretty well at jakpsatweb.cz

EDIT: scunlife brings up a good example of why I didn't think out the problem that carefully. Tables can align multiple columns simultaneously. The Question still stands (I'd like to see different CSS techniques used for alignment/layout) - although solutions that can handle his? more involved example definitely are preferred.

+8  A: 

What I usually do is :

<form>
 <label for="param_1">Param 1</label>
 <input id="param_1" name="param_1"><br />
 <label for="param_2">Param 2</label>
 <input id="param_2" name="param_2"><br />
</form>

and in a CSS :

label,input { display: block; float: left; margin-bottom: 1ex; }
input { width: 20em; }
label { text-align: right; width: 15em; padding-right: 2em; }
br { clear: left; }

Of course, you'll have to define the width according to your actual data :-)

  • First, give label and input display: block, so that it can be assigned a size and be lined up.
  • They both get float: left because Explorer does things a bit differently
  • Format the label nicely
  • hack the br so that there's a clear: left somewhere, and I remember that putting it on the label didn't work on some browser.

Plus, with the br you get a nice formatting even if the browser does not support CSS :-)

mat
This is indeed what I thought of first, its pretty clean and understandable. I was hoping there would be other solutions that could allow for a dynamic column width for the left column
Jimmy
Well, if you want dynamic column width, you have to do your boxes the other way around, that is, all the labels, and all the inputs, and there, you will certainly loose horizontal alignment :-)
mat
I agree with mat.
Saif Khan
suppose you use 'white-space:nowrap' and specified line-height? could you get away with it?
Jimmy
oh wait, yeah, then you lose vertical fluidity. hmm.
Jimmy
well, you could get away with almost everything :-)The problem here would be that, hum, you have no way of knowing 1) the right line height, 2) if some browser won't have the idea of rendering it differently, and 3) what will it do without CSS as it would destroy the "normal" flow of the document.
mat
a no-no to the br tag. with this layout you could just have said label { clear:left }
Steve Perks
Supporting Steve. Also, don't forget `fieldsets` , as they are extremely useful for complex, yet meaningful layouts.
voyager
A: 

I was thinking of something like:

<div style="text-align:right; float:left;">
    Name: <input /> <br />
    Social Security Number: <input /> <br />
</div>

which, if the right column is fixed-length, aligns OK with variable text length, but I wonder what are the disadvantages of this method?

Jimmy
+4  A: 

The trick is when the form gets more complicated than your sample, you realize that tables enable a "flexible grid" that no other elements do.

e.g. what if the "input" is more complicated than a text box? e.g. a bunch of radio buttons, each with their own label:

Color: [____Red___][v]
 Hood: [*] 
 Size: (_) Small
       (_) Medium
       (_) Large
       (*) X-Large

If all you need are simple forms, CSS is great, but as soon as you need a grid, things get interesting...

If you really want to do this, I would check out The Man In Blue's Solution, it works pretty well and is very clean.

scunliffe
This could b handled with positioning.....great article in CSS mastery in this.
Saif Khan
yeah this is interesting :) good example too.
Jimmy
You effectively can use a fieldset to do that, or a dd/dt/dd combination.
mat
+2  A: 

People talk about tables getting their forms to display the way they want, that's true, ONLY if you want to display your forms in columns and are willing to lose semantic meaning. With the following HTML in place, it's possible to display this form in as many layouts as you might wish.

BTW - No to the <br />

<form>
 <fieldset>
  <legend>Personal Info</fieldset>
  <div>
   <label for="name">Name</label>
   <input id="name" name="name" />
  </div>
  <div>
   <label for="ssn">Social Security Number</label>
   <input id="ssn" name="ssn" />
  </div>
 </fieldset>
</form>

You can clear the <divs> or set them to overflow: hidden to ensure that the floats are cleared.

Options from the above html:

Name |==============|    SSN |==============|

Name |==============|
SSN |==============|

Name     |==============|
SSN      |==============|

    Name |==============|
     SSN |==============|

   Name: |==============|
    SSN: |==============|

Name:
|==============|
SSN:
|==============|

All of the above can be accomplished with just a few lines of css.

When it comes to radio, checkboxes, and submit buttons it gets a little more complicated, but clean semantic HTML CAN be displayed the way you want it using css.

Steve Perks
How would you add the ':'s through CSS?
John
Not supported everywhere, but the :after pseudo-element will do it. This actually fits in nice with semantic HTML as a screen reader doesn't have to read it.
Steve Perks
sorry, to be more precise: label:after {content: ":"}
Steve Perks
Gotcha; I wasn't aware you could alter the content through a style
John
+1  A: 

Although the other suggestions are probably better for getting a flexible layout, the literal answer to the question is something like:

<form action="www.example.com">
    <div class="table">
        <div class="tbody">
          <div class="tr">
            <div class="td"> <label for="name">Name</label> </div>
            <div class="td"> <input id="name"> </div>
          </div>
          <div class="tr">
            <div class="td"> <label for="ssn">Social Security Number</label> </div>
            <div class="td"> <input id="ssn"> </div>
          </div>
        </div>
    </div>
</form>

with

    <style type="text/css">
        div.table { display:table; border-spacing:2px; }
        div.tbody { display:table-row-group; }
        div.tr { display:table-row; }
        div.td { display:table-cell; vertical-align: middle; padding:1px; }
    </style>

This works with the latest versions of Firefox, Chrome, Opera, and Safari. It also works with IE8 Beta 2 (standards mode). It doesn't work with IE7 or earlier, but "progressive enhancement" and all that.

Alohci
Shame rowspan and colspan don't work (I just tried in Firefox 3.0.6)
finnw