colinramsay.co.uk

Lightweight CSS Forms

10 Jun 2007

For ages, I'd style my forms up using a container div to wrap each item within the form. It always seemed a bit wasteful, so I've been trying out an alternative.

Here's my old code:

<form action="/submit/" method="post">

	<label for="name">Name</label>
	<input id="name" name="name" />

	<button type="submit">Submit</button>
</form>

It's a bit wasteful though, because every field in the form is wrapped by a div. And in order to make it so clicking on a label gives the associated form element focus, you have to add a "for" attribute on the label and a matching "id" on the form element. So you've got a fair bit of cruft just to implement a form field.

My ideal markup for this situation would be:

<form action="/submit/" method="post">
	<label>Name <input name="name" /></label>
</form>

There's not a bit of cruft there! But the advantage of the first approach is that your containing

gives you a lot of flexiblity when it comes to styling. With this second approach, getting the label text and the form field where you want them through the power of CSS is a lot trickier, but fortunately I do have those tricks up my sleeve. CSS has the position:absolute rule, which causes the element you use it with to be pulled out of the document flow and positioned with regard to the document. But there's a useful caveat to this; if that element is contained within another element which has position:absolute or position:relative applied, then the child element will be positioned with regard to its parent. An excellent interactive example of this concept can be seen at Quirksmode's position declaration page.

So, what we do is give our <label> position:relative. Without specifying a top, bottom, left or right value for this positioning, it won't affect the position of the label onscreen, but it will mean that the <input> inside can now be positioned absolutely with regard to the label. Using this knowledge in conjunction with text-align on the label, to set where the label text will appear.You can see a couple of examples of this technique on the sample page I've built. I've only been using this method for a short time but the simplicity of it appeals to me. However if you do come across any limitations then I'd love to hear about them.

Feedback or questions on this post? Create an issue on GitHub.