In other entries I’ve discussed the correct markup and best practices to make a well-structured, semantic, form. The appearance of the form has been a secondary consideration while I emphasized how important it was to not add extra markup. Forms are not paragraphs, and they do not need <br> tags or to display correctly. That is, not surprisingly, the role of CSS.

Step One: Clarify Accesskey Shortcuts

Part of the process of designing a good form is using markup to make it accessible by users of differing abilities. Each label in our form should have a unique accesskey value. While correctly configured browsers will make these accesskey options obvious to users that need them, we want to make sure that everyone who desires to use them is very clear on which shortcuts are present. If you’ve consistently used the first letter from the text of the label for an accesskey, (which is recommended) the CSS to achieve this is very simple:

label:first-letter {
	font-weight: bolder; 
	color: red;
}

(Of course, you can customize the appearance of the first letters in any way you wish).

Sometimes using the first letter of every <label> is impossible, simply because it has been used elsewhere in the form, or because that key press combination is reserved by the system. In that case, you must use other characters in the <label> text.

A good example of this would be two separate fields in a form, one asking for a phone number and the other for a postal code. We cannot use “p” as an accesskey value for both fields. This means adding a little markup to our HTML. To this:

<label for="postalcode" accesskey="c">
	Postal Code
</label>
<input type="text" name="postalcode" id="postalcode" pattern="[A-Za-z][0-9][A-Za-z] [0-9][A-Za-z][0-9]">
<label for="phonenumber" accesskey="n">
	Phone Number
</label>
<input type="tel" name="phonenumber" id="phonenumber" pattern="\d{3}[\-]\d{3}[\-]\d{4}">

We add the following inside the <label> for each element:

<label for="postalcode" accesskey="c">Postal
<span class="shortcutkey">C</span>ode</label>
<label for="phonenumber" accesskey="n">
	Phone <span class="shortcutkey">N</span>umber
</label>

And change the CSS to:

label span.shortcutkey {
	font-weight:
	bolder-color: red;
}
Elegant form (charlotteswebdesign.ca)
An elegantly designed form by Megan Ray

Step Two: Make The Form Presentable

There are many possibilities for cleaning up the appearance of our form via CSS. Let’s start with the simplest:

Option 1: Label and input on separate lines

This set of declarations forces each label on its own line, keeping the submit button by itself through the use of an attribute selector:

label, input[type="submit"] {
	display: block;
}
label {
	display: block;
}

Option 2: Label and input on same line, evenly spaced

Many designs call for <label> elements to be beside their associated form fields, to save on space. In that case, there are two possibilities. The first is an extension of the technique we just used:

label {
	display: block;
	width: 10em;
	clear: left;
}
label, input {
	float: left;
}

The CSS reads as follows: when the browser encounters a new <label> tag, display it as a block element (so we can give it a width), and make sure that everything is cleared to its left (i.e. nothing comes before it on the line, or influences where the line falls). That will force each element onto a new line when it appears, floating to the left of the following element.

The only problem you may encounter with this technique would be putting two input tags next to each other, such as a divided postal code, or an area code and phone number. In that case, you could overrule the embedded or linked style with an inline style on the affected element.

Option 3: Label and input on same line, label evenly spaced

Another possibility for lining up our labels comes from using variants of display: table, the basics of which we covered in a previous section. Essentially, we want our labels to act as if they are in a single column of a table, which should make the width provided to them exactly the same. To the HTML we have used above, we apply the following CSS:

label, input {
	display: table-cell;
}

The problem is that the browser does not know when to place label-input pairs on a new line. We’ll do so by adding a <div> around each pair, and adding appropriate CSS:

<div>
	<label for="postalcode" accesskey="c">
		Postal Code
	</label>
	<input type="text" name="postalcode" id="postalcode" pattern="[A-Za-z][0-9][A-Za-z] [0-9][A-Za-z][0-9]">
</div>
<div>
	<label for="phonenumber" accesskey="n">
		Phone Number
	</label>
	<input type="tel" name="phonenumber" id="phonenumber" pattern="\d{3}[\-]\d{3}[\-]\d{4}">
</div>

As they are block elements, each <div> will automatically divide the label-input pairs onto separate lines. The <div> elements are only used in the context of a <form> with valid markup, so we can use a descendant selector in our declaration:

form div {
	display: table-row;
}

Now, in addition to placing the label-input pairs on separate lines, each <div> also acts like a table row, meaning that each column of implied “cells” takes up the same width.

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.