Call (877) SITE-OPT (748-3678)

Accessible CSS Forms: Using CSS to Create a Two-Column Layout

Summary: Websites have become less accessible and more complex over time according to recent studies. Learn how to buck the trend by creating fast, accessible CSS forms that work with modern browsers and gracefully degrade.

In a recent study of web design patterns, Dr. Melody Ivory found that accessibility is the most underutilized aspect of good web page design (Ivory 2005). In fact websites have become more complex and less accessible over time (Hackett 2003). Less than 20% of the Fortune 100 have websites that are fully accessible (Loiacono 2004). Accessible forms are one way to combat this disturbing trend. With CSS layout, you can create two-column forms without the use of tables to save space and time. This article shows how to create a simple two-column contact form using CSS to style structural elements that is both fast and accessible.

A survey of CSS-based forms revealed many variations on a theme (see Vandersluis 2004). Most use block-level floats and margins to position form elements on the page. However, in my testing I found IE5.x Mac to have rendering problems with many of these forms. After numerous iterations, I arrived at a solution that worked for IE5.x Mac as well as Safari 1.07 Mac, Firefox 1.07 Win/Mac, IE 6 Win, Camino, and Opera. Our goal here is to create a simple accessible contact form without the use of tables (see Figure 1).

css forms layout example

Figure 1: CSS Forms Layout Example (image)

Table-Based Contact Form

First let's look at the old way of laying out a form. Tables use columns and rows to align labels and input fields (see Figure 2).

<form action="http://www.example.com/submit.cgi" method="post" class="ft">
<table>
	<colgroup><col align="right"></col><col align="left"></col></colgroup>
	<tr><th colspan="2"><h3>Personal Information</h3></th></tr>
	<tr><th>First name:</th>
		<td><input type="text" name="firstname" value="" title="first name"><td></tr>
	<tr><th>Last name:</th>
		<td><input type="text" name="lastname" title="last name"></td></tr>
	<tr><th>Email:</th>
		<td><input type="text" name="email" title="email"><td></tr>

	<tr><th colspan="2"><h3>Comments</h3></th></tr>
	<tr><th>Your comments:</th>
		<td><textarea name="comments" rows="3" cols="20" title="comments"></textarea></td></tr>
	<tr><td></td><td><input type="submit" value="Send"> <input type="reset" id="reset"></td></tr>
</table>
</form>

Note how much of the XHTML code is used for layout. Note also that this is an minimalist example with little or no accessibility features. The resulting table looks something like this rendered in a browser.

Personal Information

First name:
Last name:
Email:

Comments

Your comments:

Unfortunately, laying out a form with tables can make it difficult to access for folks with disabilities. Table-based layout also lowers your content to markup ratio, which reduces potential SEO rankings and speed. Fortunately there is a better way, CSS layout.

Building a CSS-based Form

The key to any CSS conversion project is to strip down your XHTML to bare structural elements, and then use CSS to contextually target as much style and layout as possible using few embedded classes or IDs. Forms are no different. What the table-based form above is missing are semantic elements the W3C provides in the (X)HTML specifications, namely FIELDSET and LABEL. Although they can be funkily interpreted for background colors, FIELDSET and LABEL give logical order to FORMs. FIELDSET groups like-minded form input fields and LABEL FOR links field labels with input fields through the ID attribute to make them more accessible and eminently stylable. Let's take the above table-based form code and strip it down to the bare essentials.

<form action="http://www.example.com/submit.cgi" method="post" name="f">
	<fieldset>
		<legend>Personal Information</legend>>
			<label for="firstname" accesskey="f">First name: </label>
				<input type="text" id="firstname" name="firstname" value="" tabindex="1">
			<label for="lastname" accesskey="l">Last name: </label>
				<input type="text" id="lastname" name="lastname" tabindex="2">
			<label for="email" accesskey="e">Email: </label>
				<input type="text" id="email" name="email" tabindex="3">
	</fieldset>
	<fieldset>
		<legend>Comments</legend>
			<label for="comments" accesskey="c">Your comments: </label>
				<textarea id="comments" rows="3" cols="20" name="comments"></textarea>
				<input type="submit" value="Submit" tabindex="4"> <input type="Reset" tabindex="5">
	</fieldset>
</form>

This barebones contact form contains the same fields, but they are now surrounded by semantic markup, not layout. The first FIELDSET groups the personal data together, while the second groups the comment field into one group. This style-free form looks like this (see Figure 2).

unstyled css forms layout example

Figure 2: Unstyled CSS Form Layout Example (screenshot)

Add CSS Float, mix well

The key to laying out a two-column form is to float the label (and input in some cases) element thus:

form label { 
	display: block;  /* block float the labels to left column, set a width */
	float: left; 
	width: 150px; 
	padding: 0; 
	margin: 5px 0 0; /* set top margin same as form input - textarea etc. elements */
	text-align: right; 
}

Note that CSS purists may object to the fixed width, attempts at relative widths using ems or percentages were met with browser rendering problems. The above code creates a two column layout using the label and input elements of the above form. Note that for multiple elements placed after one floated label the second and subsequent elements may break left. Since we use only one input element per label, we're on safe ground here. Later on we'll show how to indent instructive text to the second "column" with a margin-left command.

Set Form Width

Next we set a width for our form and style the fieldsets. Note how we use the form element to set a min/max width. Unfortunately fieldsets are not rendered identically by different browsers. Backgrounds can overlap, padding doesn't behave, and they tend to take up the entire width of the screen on Internet Explorer. Auto, ems, and percentages were tried, but the form misbehaved stretching this way and that. A pixel value larger than the largest anticipated font size did the trick, avoiding wrapping. However we chose to set the width using the form element, which bypassed the problem.

form {  /* set width in form, not fieldset (still takes up more room w/ fieldset width */
  font:100% verdana,arial,sans-serif;
  margin: 0;
  padding: 0;
  min-width: 500px;
  max-width: 600px;
  width: 560px; 
}

form fieldset {
  / * clear: both; note that this clear causes inputs to break to left in ie5.x mac, commented out */
  border-color: #000;
  border-width: 1px;
  border-style: solid;
  padding: 10px;        /* padding in fieldset support spotty in IE */
  margin: 0;
}

Bump up Legend Size and Underline First Letter

Next we bump up the legend font size and underline the first letter of our labels to signify our access keys. Note that Firefox 1.07 Win and Explorer 5.2 Mac do not appear to support the first-letter pseudo-class on legend elements. Opera also breaks the legend after the first letter underlined (despite attempts to fix this with white-space:nowrap;, see Figure 3).

opera breaks first letter legends

Figure 3: Opera Breaks First-Letter Underlined Legends

Due to these legendary problems (thanks to readers below who pointed the Opera problem out) we switched to underlining the first letter in our labels (form fieldset label:first-letter;) which works on all browsers tested and requires accesskey attributes in each input field.

form fieldset legend {
	font-size:1.1em; /* bump up legend font size, not too large or it'll overwrite border on left */
                       /* be careful with padding, it'll shift the nice offset on top of border  */
}

form fieldset label:first-letter { /* use first-letter pseudo-class to underline accesskey, note that */
	text-decoration:underline;    /* Firefox 1.07 WIN and Explorer 5.2 Mac don't support first-letter */
                                    /* pseudo-class on legend elements, but do support it on label elements */
                                    /* we instead underline first letter on each label element and accesskey */
                                    /* each input. doing only legends would lessen cognitive load */
}

Break Clear of the Ordinary

We need to clear our floats somehow, and clearing on the structural elements didn't work in all browsers tested, so we used a BR element, which also helps our form gracefully degrade for older browsers.

form br {
	clear:left;
}

Miscellaneous Tweaks and Workarounds

Indent Instructions to Second Column

To add instructions to the right column you can set a left margin equal to the accumulated indent of the input fields. This is simpler than using a dummy label element.

form small {
	display: block;
	margin: 0 0 5px 160px; /* instructions/comments left margin set to align w/ right column inputs */
	padding: 1px 3px;
	font-size: 88%;
}

Dummy Label Element

Speaking of which, we found that the alignment of our submit and reset buttons was more consistent using a dummy label element than a left margin. You can use the above technique to indent these elements but we found the positioning was inconsistent between browsers. We were trying to avoid CSS hacks and browser sniffing so the "kludge" label was the most expedient method (this could be renamed as "submit" for clarity).

<label for="kludge"></label>
	<input type="submit" value="Send" id="submit">...

CSS Gotchas

One gotcha to watch out for is in the notoriously finicky IE5 Mac. If you specify display: inline for the input and textarea elements they break left in IE5x Mac (see Figure 4).

form input, form textarea {
	display: inline; /* inline display must NOT be set or will hide submit buttons in IE 5x mac */
	width:auto;      /* set width of form elements to auto-size, otherwise watch for wrap on resize */
	margin:5px 0 0 10px; /* set margin on left of form elements rather than right of
                              label aligns textarea better in IE */
}

ie5 mac breaks with inline

Figure 4: IE5x Mac Breaks Left with Display Inline

Floating Safari Hides Input Buttons

Make sure you test your creation in Safari as well. We ran into disappearing or obscured buttons when floating both labels and input elements (see Figure 5).

safari mac hides buttons

Figure 5: Safari Mac Can Hide or Obscure Buttons

If you do choose to float your inputs, we surmise it is the floats applied to our input buttons, removing floats and displaying inline solved the problem (see code below). We chose to avoid the problem entirely by floating only our labels.

form input#submit, form input#reset { 
	float: none; 
	display: inline; 
	margin:0;
	padding:0;
}

Padding the Cellmates

We tried adding padding between the flush right labels and flush left input elements using margins and padding on the right side of our labels. This didn't work as well as we would have hoped, giving inconsistent positioning on our textarea element. Adding margins to the left of our input and textarea form elements worked more consistently in IE6 Win.

form input, form textarea {
	...
	margin:5px 0 0 10px; /* set margin on left of form elements rather than right of
                              label aligns textarea better in IE */
}

The final product can be seen below and in a separate CSS form complete with JavaScript to focus the cursor in the first input element.

Bold fields are required. Underlined letters are accesskeys.

Personal Information


Your email address is safe with us, until we're acquired.
Comments

Here is the CSS and form code.

<style type="text/css">
<!--

form {  /* set width in form, not fieldset (still takes up more room w/ fieldset width */
  font:100% verdana,arial,sans-serif;
  margin: 0;
  padding: 0;
  min-width: 500px;
  max-width: 600px;
  width: 560px; 
}

form fieldset {
  / * clear: both; note that this clear causes inputs to break to left in ie5.x mac, commented out */
  border-color: #000;
  border-width: 1px;
  border-style: solid;
  padding: 10px;        /* padding in fieldset support spotty in IE */
  margin: 0;
}

form fieldset legend {
	font-size:1.1em; /* bump up legend font size, not too large or it'll overwrite border on left */
                       /* be careful with padding, it'll shift the nice offset on top of border  */
}

form label { 
	display: block;  /* block float the labels to left column, set a width */
	float: left; 
	width: 150px; 
	padding: 0; 
	margin: 5px 0 0; /* set top margin same as form input - textarea etc. elements */
	text-align: right; 
}

form fieldset label:first-letter { /* use first-letter pseudo-class to underline accesskey, note that */
	text-decoration:underline;    /* Firefox 1.07 WIN and Explorer 5.2 Mac don't support first-letter */
                                    /* pseudo-class on legend elements, but do support it on label elements */
                                    /* we instead underline first letter on each label element and accesskey */
                                    /* each input. doing only legends would  lessens cognitive load */
                                   /* opera breaks after first letter underlined legends but not labels */
}

form input, form textarea {
	/* display: inline; inline display must not be set or will hide submit buttons in IE 5x mac */
	width:auto;      /* set width of form elements to auto-size, otherwise watch for wrap on resize */
	margin:5px 0 0 10px; /* set margin on left of form elements rather than right of
                              label aligns textarea better in IE */
}

form input#reset {
	margin-left:0px; /* set margin-left back to zero on reset button (set above) */
}

textarea { overflow: auto; }

form small {
	display: block;
	margin: 0 0 5px 160px; /* instructions/comments left margin set to align w/ right column inputs */
	padding: 1px 3px;
	font-size: 88%;
}

form .required{font-weight:bold;} /* uses class instead of div, more efficient */

form br {
	clear:left; /* setting clear on inputs didn't work consistently, so brs added for degrade */
}
-->
</style>
<script>
<!--
function sf(){document.f.firstname.focus();}
-->
</script>
</head>
<body onLoad=sf()>

<form action="#" method="post" name="f">
<p><b>Bold</b> fields are required. <u>U</u>nderlined letters are accesskeys.</p>
<fieldset>
<legend>Personal Information</legend>
	<label for="firstname" accesskey="f">First name: </label>
		<input type="text" id="firstname" name="firstname" tabindex="1" value="" title="first name"><br>
	<label for="lastname" accesskey="l">Last name: </label>
		<input type="text" id="lastname" name="lastname" tabindex="2" title="last name"><br>
	<label for="email" class="required" accesskey="e">Email: </label>
		<input type="text" id="email" name="email" tabindex="3" title="email"><br>
		<small>Your email address is safe with us, until we're acquired.</small>
</fieldset>
<fieldset>
<legend>Comments</legend>
<label for="comments" accesskey="c">Comments: </label>
	<textarea name="comments" rows="3" cols="23" id="comments" tabindex="4" title="comments"></textarea><br>
<label for="kludge"></label>
	<input type="submit" value="Send" id="submit" tabindex="5"> <INPUT type="reset" id="reset" tabindex="6">
</fieldset>
</form>

Multicolumn Forms

More complex forms can be done with CSS, with similar techniques used for 3 and 4-column layouts. You can float notes and additional columns within this framework.

Conclusion

With careful use of CSS and lots of browser testing you can create two or three-column forms using CSS layout. Be sure to test your creation in as many browsers as possible (you can use Browsercam as well). We found that designs that worked well in some browsers would break in others (especially IE 5.x Mac). By marking up your forms with structural elements and targeting those elements with CSS contextual selectors you can create a fast-loading form that is SEO friendly and accessible.

Further Reading

Accessible Forms
A succinct tutorial on the elements of accessible forms by Roger Hudson.
Accessible Forms: Guidelines, examples, and accessible JavaScript tricks
A list of form guidelines based on web standards and current accessibility guidelines from websemantics.co.uk.
Belorussian Translation of this article
provided by ucallweconn with permission.
CSS-only, Table-less Forms
Jeff Howden's take on CSS form layout. Uses DIVs to group labels and form inputs rather than breaks.
CSS2 - Tableless Forms
Peter-Paul Koch's version uses cleared breaks, the technique shows in this page uses the cleared break technique for brevity and backwards compatibility.
Form Layout with CSS: A Small Literature Study
Bobby Vandersluis surveys different form layout techniques and offers some commentary re XFORMS and further reading.
Hackett, S., Parmanto, B. and Zeng, X. (2003), "Accessibility of Internet Websites through Time,"
In a wayback machine study of 154 unique websites from 1997 to 2002 Hackett and company found that random websites have become progressively less accessible and more complex over time. Government websites have also become more complex over time, but have maintained their accessibility (in part because they are required by law to do so). The researchers conclude that added webpage complexity (scripts, animation, Flash etc.) inadvertently creates barriers to accessibility for users. In ACM SIGACCESS Conference on Assistive Technologies, Proceedings of the 6th international ACM SIGACCESS conference on Computers and accessibility, Atlanta, GA, USA, pp. 32 - 39.
How to Style forms in CSS
Author Jason Teague shows how to style forms with CSS in this multi-part article.
Introduction to Web Accessibility
Resources from the W3C.
Ivory, M. and Megraw, R., (2005), "Evolution of Web Site Design Patterns,"
In a longitudinal study of highly rated web sites from 2000 to 2003 Ivory and Megraw found that the "most glaring deficiency of web sites, even for sites that are highly rates, is their inadequate accessibility, in particular for browser scripts, tables, and form elements." ACM Transactions on Information Systems, v. 23:4(2005):463-457.
Loiacono, E. (2004), "Web Accessibility of Corporate America,"
Loiacono found that less than 20% of Fortune 100 websites are fully accessible to people with disabilities. In Communications of the ACM, v. 47:2, pp. 82-87. Dec. 2004.
Online Accessibility: Forms
Form accessibility tutorial from the accessibility lab at Michigan State University.
Real-World Style
This example uses spans and divs, omitting structural form markup, not recommended.
Simply Accessible
A brief presentation on designing accessible forms by Derek Featherstone.
Sullivan, T. and Matson, R. (2000), "Barriers to use: Usability and content accessibility on the web’s most popular sites,"
Found that more than half of the web's 50 most popular websites were partly accessible or inaccessible. In Proc. of CUU'00, pp. 139-144, ACM Press, 2000.
Techniques for User Agent Accessibility Guidelines
Includes accessible form techniques from the W3C.

By website optimization on 30 Mar 2006 AM

Copyright © 2002-2013 Website Optimization, LLC. All Rights Reserved - Free website speed test - Privacy Policy
Last modified: August 26, 2013.

Follow us on: Twitter, Google+, Facebook, Linked In