Bulletproof Web Forms Part Three: Style
When web developers abandoned tables, they left behind a vacuum when it comes to forms, and since then form presentation has taken a step backward. Perhaps the most common CSS form design is to align the textual labels to the right along an invisible axis and then align form elements to the left of the axis creating the illusion of a table-like grid while keeping mark-up and CSS small and semantic. Many users find right-aligned text to be more difficult to read, and so balancing your form on an invisible axis can create an unnecessary hurdle for users.
Presentation translates to accessibility for desktop users
Users are accustomed to seeing grids because a great deal of design is based on a grid. Furthermore, internet users are accustomed to using forms that are laid out in tables, so they expect to see a logical and rigid presentation. To meet the needs of these users, it is important to offer an orderly presentation. Now we'll review our mark-up from part two and reveal the reason for its structure. I should mention that style is a personal thing, so I'll cover the core styles, and the rest is up to you to personalize your forms.
To style our form, we want to use the fewest rules possible, and we're going to emulate a table-based layout. A quick gander at the mark-up shows that the <label> elements translate well to rows, so we'll start there. We set the label to display: block, and we can further decorate it as desired.
The text description within our <label>s enters next. You'll have noticed that the text is housed in its own <span>, and that's because it will behave as a column on the left side. In addition to giving those spans a width, we set those to also display: block; float: left; width: 8em. NB: width can also be declared as a percentage, or a pixel value.
We want the form elements to make a square edge on the right side of the form; 18em will do. But we don't want to style every <input> on the page because that'll make for some ugly checkboxes and submit buttons, so we'll use the CSS attribute selector like so: input[type="text"] { width: 18em; } Your alternatives to using the attribute selector are to use a specific class on various form elements, and then style the classes. Depending on your target browser, you may find that to be a better solution.
What about Internet Explorer?
Since IE doesn't understand advanced CSS like attribute selectors, we'll need to dumb down our CSS a bit and add more than a few class attributes to our form if we want a straight right-side edge. If you don't care about having a square right edge in IE, then by all means skip this section.
Let's get started with a simple declaration of * html input { width: 18em; } This sets the width properly, but it adversely affects the presentation of the submit button, radio buttons and checkboxes. The fix to our oversized elements is to set the width to auto for all of the non-text elements. To appease IE, you'll need to add a class to each checkbox, radio button and declare its width to be auto. We've already assigned a special class to the submit button, so * html .submit { width: auto; } will get you started and show the concept.
I'm going to leave the right edge jagged in this example because I don't want to dwell on IE, and I don't want to inject too much extra mark-up and CSS into the example. Using a special class on applicable elements and styling it appropriately (width: auto;) will get the task done, and implementation is left to the reader. I will, however, show the same form in its finished state outfitted to display properly in IE at the end of this article for reference.
Bulletproofing the layout.
Floating all of these elements can quickly create a jumble of the form, but it's simple to rein it all in. We accomplish this by setting the <label>s to clear: left and now each row falls into place. What's more is that not only do we have cohesive rows, no matter how much or how little content the text description has, and no matter what the size of the form element, the rows do not break! It's as durable as a table, and the grid pattern is maintained. Since the label text is contained within its own container (a <span>) and that container's width is set to 8em, you can count on the width to remain constant and text will not overflow its bounds.
An important caveat regarding clear and float: The W3 spec says that an element set to clear will clear any preceding floated element. So if you have a column in your layout (like the navigation or a side bar) that is floated and appears in the mark-up before your form, you are likely to encounter problems. The solution is to either order your mark-up so that the content is first, or to be sure that the form itself is in a floated container. Bear in mind, this only applies if you're using floats in your document before the form.
Required
It has become something of a standard to denote required fields with an asterisk — fashionably a red one — to let the user know that the form will be obstinate if it isn't properly filled-in. An asterisk, however, is just a symbol that alerts the user of more information similar to an icon or a footnote. So we fire up an image editor and create an appropriate icon to replace this text on screen. Since a red asterisk is common, we'll just use an image of one, and we'll also put a note on the page that indicates its meaning. This is a pretty simple job for CSS, we first make the <em> display: block, and we hide the word "Required" by applying text-indent -9999em. Then we apply the background image and set the width and height to match our asterisk image. I've also set its margin-left to a negative value because I want the icon to hang off the right column. This way it doesn't interfere with the orderly left edge of the form elements. It's a good idea to include a note on the page that states fields marked as <em>Required</em> are required, and be sure that your <em> is styled the same way. This is just more accessibility for visual users.
A little polish
Depending on the width of your <fieldset> and the width of your form, you may have trouble with your submit button. Apply clear: left; to it, and it'll wrap to its own line.
Some browsers can be unkind to the last <label> in a <fieldset> — particularly if the <label> contains a lot of text. There is more than one solution, and among them are overflow: auto applied to the label, generated hidden content, applying a special class or id to the last <label>, or even just adding a breaker at the end of the fieldset. The technique you use is up to you, positioniseverything is a good place to start.
Variations on the theme
Every once in a while you'll encounter a form that has some variation. Perhaps it's an indented set of radio buttons, or maybe a series of checkboxes. Either way, it's often appropriate to break the grid. In these instances, I will group my set of checkboxes into their own logical division (that's geek for <div>). It is structurally correct to do so, and by applying an id or class to the div, I've got all the hooks I need to dig in with CSS. Since the declarations to achieve the grid are few, they are easy to override with a new div.
Voila
We now have a semantically appropriate, accessible, good looking form, and we didn't use a single table! Our layout is bulletproof, and users will be able to fill-in the form quickly and easily. In the coming days or weeks, I'll be supplementing this series with an article on behavior in forms so we can add in a slick javascript layer to make the form even easier.
See the example form outfitted for IE.
- under:
- Web Development
- Posted on
- 2006-04-03
Comments:
An excellent read, I was wondering when I would get to see this article. This is a great way to finish off those presentational tables. One suggestion if I may: red might not be a good color to use for the asterisks on the required fields, since red is generally synonymous with error messages. By the way, great use of the label element. Could part 4 be in the works? Possibly throw some FauxJAX in there too?
Thanks! I also just fixed a bunch of bad links I had no idea about. oops.
Yes, part four is in the works, and it'll be complete with fauxjax, it's just a matter of polishing up the copy I've written so far. Too many projects, too little time!
Red may not be the best color, that's true. But it's certainly a common color. I tend to use red for error messages too. I suppose that it's ultimately up to the author. What's important to remember is that it's an icon that is substituted for actual text, so whatever icon is chosen, it's wise to explain it somewhere on the page. Also of note is that a page that relies on color to convey information doesn't meet the most lenient of accessibility guidelines, so a more descriptive icon is certainly appropriate.
I like the article but 1 minor thing. Shouldn't the submit button be outside the fieldset? After all, that submit button is sending all the info in that form, not just what's in the last fieldset.
Semantically speaking, I would agree with you. I don't think that the submit button necessarily belongs in the fieldset. I can see the argument for or against, but I'm inclined to side with your opinion.
However, placing an input directly in the form (not within a fieldset) makes the w3's validator throw errors. I think it's just a glitch in the validator, but I'm not sure. The answer no doubt lies in the XHTML spec, but I haven't had a chance to decipher it again to be sure.
Nice post. Thanks for the clear/float caveat. That one had me scratching my head for a couple of minutes. A List Apart also has a nice article on styling forms.
This article is closed to further commentary. But you can always contact me directly.