Create a stylish accessible form

Written July 1, 2009. 14 comments.

form

There are a stack of different ways to lay out a form, but honestly sometimes I’m undecided on which way is better. Some say there’s nothing wrong with using a table to position your form elements, but I reckon that makes it semantically meaningless.

Forms have admittedly always been a field (bad pun, sorry) of HTML that I’ve not paid as much attention to as I should have, but I recently decided to create a functional template with the intention of re-cycling it when needed.

I had several goals for this exercise. The form needed to:

The finished product can be viewed here, and the complete source and demo is downloadable at the end of this article.

The XHTML bits

As accessibility is a concern, we will surely be putting in fieldsets, legends and labels. These elements also provide us with plenty of styling options, so no complaints so far.

So here’s the form:

<form id="myform" method="post" action=""> 

<fieldset> 
<legend>Personal</legend> 
<label for="name">Name <span>(Your full name please)</span></label> <input type="text" id="name" /> 
<label for="web_site">Web Site <span>(No need to include http://)</span></label> <input type="text" value="www." id="web_site" /> 
<label for="email_address">Email Address <span>(Must be valid)</span></label> <input type="text" id="email_address" /> 
</fieldset> 

<fieldset> 
<legend>Professional</legend> 
<label for="company">Company <span>(Name of your organisation)</span></label> <input type="text" id="company" /> 
<label for="position">Position <span>(What is your title?)</span></label> <input type="text" id="position" /> 
<label for="duration">Duration <span>(How long have you been there?)</span></label> <input type="text" id="duration" /> 
<label for="location">Location <span>(Seriously, where are you?)</span></label> 
<select name="Location" id="location"> 
<option value="Australia"></option> 
<option value="Australia">Australia</option> 
<option value="Outside Australia">Outside Australia</option> 
</select> 
</fieldset> 

<fieldset>
<legend>Battlestar Pop Quiz</legend> 
<label>Cylon <span>Who is a among the final five?</span></label> 
<input type="radio" id="adama" name="pie" class="narrow" /> <em>Adama</em> 
<input type="radio" id="anders" name="pie" class="narrow" /> <em>Anders</em> 
<input type="radio" id="hilo" name="pie" class="narrow" /> <em>Hilo</em> 
</fieldset> 

<fieldset> 
<legend>Final Stage</legend> 
<label for="comments">Comments <span>(Care to leave a comment?)</span></label> <input type="text" id="comments" /> 
<label>Agreement <span>Tick if you agree to all this</span></label> <input name="agreement" type="checkbox" value="agreement" class="narrow" /> 
</fieldset>

<div>
<input type="submit" name="button" id="submit" value="Submit" class="submit" />
</div> 

</form>

Nothing out of the ordinary here, except I’ve placed spans within the labels with their display set to block in the CSS, which makes them fall below the label for the appearance we want.

This is better than dropping the text with a <br /> not only because we get to tweak the position with CSS, but also because it makes more sense to have this:

Name (Your full name please)

…instead of this…

Name
(Your full name please)

This is perfectly valid BTW. Ironically, the latter example is the appearance we are going for, but we’ll get there with CSS.

With the label now containing the span (consider them grouped), we can set a fixed width displayed block, floating left and text aligned right so they all appear uniformly under one another. CSS is your friend:

label { 
width:180px; /* Must match the exact width specified in the span */ 
display:block; 
float:left; 
text-align:right;

} 

span { 
display:block; width:180px; /* Must match the exact width specified in the label */ 
text-align:right; 
}

The input fields also have a fixed width and will appear uniformly under each other.

So to summarise at this stage, here’s what we’re looking at:

label_and_field.gif

The ‘block’ trick

If you know anything about floats you’re probably already wondering how these are going to line up underneath each other without some sort of containing element. In the past I would have done this by placing each in it’s own div, which is messy and unnecessary, or each in a p, which is semantically incorrect as these are not paragraphs we’re dealing with.

The trick is to have a single containing element around the entire lot, and guess what? We’ve already got one. Place an ID in the form tag, id=”my_form” I’ve used, and use CSS to set a fixed width only wide enough so that the containing elements wrap.

This will force each onto a new line giving the appearance that they are block level elements. Sneaky huh?

IE issues resolved

As is often the story, we have to make allowances for IE. In this case we’ve set a background colour on the legend, which when viewed in IE bleeds into the fieldset. This was fixed with a simple absolute positioning ‘hack’.

IE also had a nasty habit of showing borders around the radio buttons and check boxes on hover. Again it was easily fixed but still something that didn’t happen in any other browser (surprise surprise).

Compatibility

Testing went better than first expected. It works fine in Firefox 1.5, 2.0, 3.0.11, 3.5, IE6, 7 and 8, Safari, Opera and Chrome.

The download contains the complete demo with plenty of comments in the CSS to explain what’s happening.

Yours, free to enjoy for any purpose you see fit.

accessible_form.zip (7.5k)

Who is That Web Guy?

Michael is a veteran web designer / developer / usability evangelist, practitioner of W3C guidelines, and currently head of the web dev unit at Stormbox, a branding and creative communications agency located in Perth, Western Australia.

14 Responses to Create a stylish accessible form

  1. Pete Harvy says:
    I think to be totally accessible you should have used a higher contrast. But it looks fabulous and that’s just a styling issue anyway. Stupendous effort Web Guy.
  2. Paweł Krefta says:
    There are little problems in Opera 9.62 on Mac, but they are easy to fix :)
  3. CSS Babe says:
    I especially like how you put parts into separate sections. Thank you!
  4. That Web Guy says:
    You’d think the browsers would work the same regardless of platform. Given the low complexity of the HTML I suspect the fix is probably something as simple as increasing the width of the containing form by a few pixels. I had to do that to make it work in IE6. I will see if I can get my paws on a Mac today at the office to confirm.

    Thanks!
  5. Harun Smrkovic says:
    Great! I really like the style and usability.

    Hope you don’t mind it if I use it somewhere :) :)
  6. Thesorrow says:
    Is this possible to have a fluid container ?
    Is this possible to add messagesm under or on the right side of the inputs for displaying error messages…
  7. That Web Guy says:
    Go for it – “Yours, free to enjoy” I’ve added “for any purpose you see fit”
  8. Carerra Davis says:
    I’ve never been a fan of the fieldset in forms only because aesthetically they don’t usually look good. But you somehow make them look so good now I can’t imagine not using them from now on. Great work web guy.
  9. Design Demi says:
    That’s the best looking form I’ve ever seen that doesn’t have any graphical elements (except for the submit button). Thanks for letting us use it for anything we want.
  10. css freshman says:
    very good work on the form.
  11. Axcel says:
    Stunning effort web guy. I’m going to use this for an upcoming project. Thanks~!
  12. CSS Babe says:
    I just tried to put this into practice now but the fonts are all massive in Internet Explorer 7. Yours looks fine but I can’t see I’ve done anything different. Any guidance would be great.
  13. A Novice says:
    Don’t worry I figured it out. IE7 is such a POS.
  14. Maddi says:
    Brilliant! Looks great and works perfectly.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

+ 6 = eight