How I do form layouts

I originally posted this as a comment on Forrst, but since comments are only viewable by Forrst members, I am re-posting it here. Really, it's no big deal, and is pretty old-school. I just figured it might help with people beating their heads against a desk, attempting form layouts using float. Hint: don't bother.


Note: I'm not here to argue. I'm posting specifically because I was asked (by the author of this post/question) for my opinion via Twitter.

😁

https://twitter.com/kom420/status/68728880294395905

Depends on the layout I need, but I usually just go the paragraph route. Unless I need labels side-by-side with form elements, in which case the varying length (of label text) makes floats a pain. In that case, I'd do…

Side-by-side layout

<form accept="" action="" method="">
	<table role="presentation" class="form">
		<tr>
			<th>
				<label for="input_1"> Label text </label>
			</th>
			<td>
				<input type="text" id="input_1" name="input_1" />
			</td>
		</tr>
		<tr>
			<th>
				<label for="input_2"> Label text </label>
			</th>
			<td>
				<input type="text" id="input_2" name="input_2" />
			</td>
		</tr>
		<tr>
			<th>&nbsp;</th>
			<td>
				<input type="submit" value="Submit" />
			</td>
		</tr>
	</table>
</form>

Now, before anyone cries "unsemantic" — Note that this is about ease of maintenance. Floats with fixed-widths on labels only work so well, until the label gets longer. It's just not worth the hassel to constantly re-visit the CSS because of form elements changing. I'm speaking from experience, having worked at a Fortune 50 company previously (and now a Fortune 10 co.), where that type of stuff is not always under your control.

Also worth noting, is that most (maybe all?) assistive devices (screen readers) go into a different reading mode when speaking form content, so the table does not throw off its interpretation. Instead, it reads label and input combinations.

For the CSS, to force the th to be as narrow as possible, I do this…

(See form example on Formalize.me for an approximation)

.form th {
	text-align: right;
	white-space: nowrap;
	width: 1%;
}

Stacked Layout

Oh, and if I'm doing a stacked approach, where each label is above its respective input, I do this…

<form accept="" action="" method="">
	<fieldset>
		<legend>Group 1</legend>
		<p>
			<label for="input_1"> Label text </label>
			<br />
			<input type="text" id="input_1" name="input_1" />
		</p>
		<p>
			<label for="input_2"> Label text </label>
			<br />
			<input type="text" id="input_2" name="input_2" />
		</p>
	</fieldset>
	<fieldset>
		<legend>Group 2</legend>
		<p>
			<label for="input_3"> Label text </label>
			<br />
			<input type="text" id="input_3" name="input_3" />
		</p>
		<p>
			<label for="input_4"> Label text </label>
			<br />
			<input type="text" id="input_4" name="input_4" />
		</p>
	</fieldset>
	<p>
		<input type="submit" value="Submit" />
	</p>
</form>

With a bit of CSS (via sibling selector) to increase the spacing between the label and the input for browsers that understand it (Note: doesn't work in IE6)…

br + input,
br + select,
br + textarea {
	margin-top: 5px;
}