Pages

Tuesday, September 20, 2011

Table-less Forms: A Partial Solition (Source Code)

In my last two posts, I discussed what I want to see in a table-free form and the problems I had with creating one. To recap, here's what I wanted:
  • Labels lined up in the same row as form fields
  • Label column that stretches/shrinks to the size of the longest label
  • As little extra HTML as possible
My solution was to enclose <label>s in a <div> that stretches/shrinks to the width of its contents, and to use absolute positioning to push the <input>s nested in those <label>s outside the <div>. The limitations of that solution are:
  • The <label>s' height won't stretch to fit form controls taller than a line of text, such as <textarea>.
  • Since <input>s are pushed to the right, you can't put checkboxes and radio buttons before their label text unless they're outside the wrapper <div>.
  • Long labels stretch the wrapper <div>.
  • Multiple wrapper <div>s in a form won't line up with each other.
So with that in mind, here's my source code. First the CSS:
form { /* Add border to form as visualization aid */
 border: 1px solid darkblue;
}
form * {
 clear: left; /* don't let floated .formlineup break layout. */
}
.formlineup {
 display: inline-block; /* shrink to fit content. */
 float: left; /* Needed for backward-compatibility with IE6 and FF2. */
 background-color: lightblue; /* Visualization aid */
}
.formlineup label {
 display: block;
 position: relative; /* allow absolute positioning of children */
 padding-top: 2px;
 margin-top: 2px;
 padding-right: .5em;
 background: #CEF; /* visualization aid */
}
.formlineup label input {
 position: absolute;
 top: 0px;
 left: 100%; /* Push all the way outside the <label> */
 height: 1em;
}
/* <br> tags are used in case CSS breaks.
They create extra space when CSS is working, so hide them. */
.formlineup br {
 display: none;
}

Next, the HTML. Note that nothing outside of div.formlineup is really important for this demo; I put the extra fields there to show some of the things that need to be outside of the wrapper div in order to work. See the screenshot in my previous post to see what happens when you put them inside.

<form>
<div class="formlineup">
 <label for="name">
  Name:
  <input type="text" name="name" id="name">
 </label><br>
 <label for="address">
  Address:
  <input type="text" name="address" id="address">
 </label><br>
 <label for="stuff" style="clear: left;">
  Stuff:
  <input type="text" name="stuff" id="stuff">
 </label><br>
 <label for="password">
  Password:
  <input type="password" name="password" id="password">
 </label>
</div>
<fieldset><legend>Radio Buttons</legend>
 <label for="thing1">
  <input type="radio" name="thing" value="1" id="thing1">
  Thing 1
 </label><br>
 <label for="thing2">
  <input type="radio" name="thing" value="2" id="thing2">
  Thing 2
 </label><br>
 <label for="voom">
  <input type="radio" name="thing" value="voom" id="voom">
  <em>VOOM!</em>
 </label><br>
 <label for="long">
  <input type="radio" name="thing" value="long" id="long">
  This label is longer than the others.
 </label><br>
</fieldset>
<label for="spam">
 <input type="checkbox" name="spam" id="spam">
 Send Me Spam!
</label><br>
<input type="submit"><input type="reset">
</form>

Addendum: Sorry about the ugliness of the source code; Blogger doesn't feature syntax highlighting out of the box, and there's some investment of effort required to add it. I'm still debating whether I want to add it or just stick to using my Wordpress blog to post source code from now on.

No comments: