Sam Croft

Full-stack developer

Minimal form markup; simple, slender and semantic

  • 19 comments

Filed in: forms, html, semantics

Recently I have been creating a lot of forms for RITH‘s own product, Lemontree. When I create forms I’m always out to write lean markup, as semantically correct as possible while also maintaining enough CSS hooks to achieve the desired layout.

I hate forms that rely on bloated markup and for every form I create I am always left wondering whether or not I could have created something more efficient and correct.

The many different ways to markup a form

I’ve seen dozens of ways to create ‘semantic’ form markup over the years. But I don’t think I’ve found one that is super-elegant.

When considering the basic elements of a form — form, fieldset, legend, label, input, textarea, select and button — I’m always keen to keep additional markup to a minimum. Sometimes it’s entirely necessary, but most of the time when building a simple contact form… how much is actually necessary?

Let’s look at some basic markup for a simple form:

<form>
	<fieldset>
		<legend>Your details</legend>
		
		<label for="name">Name</label>
		<input type="text" id="name">
		
		<label for="email">Email</label>
		<input type="email" id="email">
	</fieldset>
	
	<input type="submit" value="Submit">
</form>

It’s semantic, logical and accessible. But styling the above can be somewhat troublesome without adding some additional hooks for CSS to make use of.

How I used to markup forms

Some of the methods for using loosely semantic hooks that I’ve seen and used over the years include:

  • using block elements such as div and p
  • using inline elements such as span, strong and em
  • using ordered lists to create a linear flow

In 2004 (or was it 2005?) I read Andy Budd’s CSS Mastery, a fantastic resource, and I favoured his technique of using p or div block level elements to markup each label and input ‘row’, creating something along the lines of:

<form>
	<fieldset>
		<legend>Your details</legend>
		
		<p>
			<label for="name">Name</label>
			<input type="text" id="name">
		</p>
	
		<p>
			<label for="email">Email</label>
			<input type="email" id="email">
		</p>
	</fieldset>

	<input type="submit" value="Submit">
</form>

Alright it works, but it’s not entirely semantically correct using a p tag to mark up a section of a form, and Andy pointed this out in the book. Having said that, it is a simple and relatively lightweight approach that was loosely semantic and I have used this approach for years myself.

Looking for a new semantic approach for marking up forms

Hellbent on marking up forms in a more elegant way I started looking at the required elements for your average form and considered the layout I normally want to achieve.

The alternative way to use the label element

Checking the W3C specification for the label tag I realised I was using the element in only one of two possible ways. My normal, and I dare say the most common use, of the label element is as follows:

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

There is another valid method though:

<label>Name
	<input type="text">
</label>

The same amount of markup, but rather than have the input element directly after, or before, the label it is wrapped within it.

This method has a couple of useful advantages. Rather than the clickable element of the label just being the label text, the entire area around the label text and the field is clickable, almost like a clickable row. Great for mobile devices. The second benefit is that you do not need to specify the input id within the label tag – the input is already associated with the label as it’s inside the element. Lovely.

I should add that ordinarily I ignore this last advantage and still use the label for attribute. It just feels more correct and keeps your forms safeguarded against any markup changes where a form field might be moved outside of a label, for one reason or another.

Adding some a style hooks

The basic premise of this technique is to set the label to be a block level element, rather than it’s default property of inline. This creates a ‘row’ if you like, for each label and form field element. Referring back to my old method, I was achieving the same appearance by using a dirty p tag. Disgusting.

Once the ‘row’ has been created there is one extra style hook required to ensure that there are enough hooks for use in a sprinkle of CSS, resulting in this slender piece of form markup:

<form>
	<fieldset>
		<legend>Your details</legend>
		
		<label><b>Name</b>
			<input type="text" id="name">
		</label>
	
		<label><b>Email</b>
			<input type="email" id="email">
		</label>	
	</fieldset>

	<input type="submit" value="Submit">
</form>

Here I add an inline tag, b, around the label text itself. I am still pondering what the best inline element to use is; strong, em, b, i or span? I have leaned towards b recently. Ordinarily I like to set the font-weight to bold for my form label‘s, but as strong carries semantic meaning and I am just looking for the visual effect b seems more appropriate…

The result is a simple, slender and semantic form:

Simple and semantic html form markup

Simple and semantic HTML form markup

The basic CSS

The CSS to style a basic form is relatively straightforward using this method of markup. These are the rules that I currently use:

form label {
	display: block;
	float: left;
	clear: left;
	margin: 10px 0;
}
	form label b {
		display: block;
		float: left;
		width: 80px;
		margin-right: 20px;
	}
	form label input,
	form label textarea,
	form label select {
		float: left;
		width: 180px;
	}
	form label input[type="radio"],
	form label input[type="checkbox"] {
		width: 20px;
	}
form p {
	clear: left;
	margin: 10px 0 0;
}
form input[type="submit"] {
	margin-left: 100px;
}

I should point out a few things here…

Lines 19-22: I am using the attribute selector to target radio and checkbox input elements to reset their width, as Firefox is the only browser that will allow these types of elements to have an altered width (see lines 13-18).

Lines 23-26: A p tag?! Yes, after that rant about not using p tags I do use them in forms, but sparingly and only to markup a title for a series of checkbox or radio options. Perhaps a heading tag would be more appropriate…

Lines 27-29: Again, I am using the attribute selector to target the submit button, as this requires a separate rule as it is not contained within a label.

Using this lean markup and CSS one can create a form that is simple, slender and semantic.

About the author

I'm Sam Croft a full-stack developer with over 15 years experience in web and app development. For the last six years I have been a partner of Running in the Halls, an app and game design studio based in Huddersfield, UK. During this time I have developed many web and applications. Highlights include a node.js/socket.io app to create the worlds largest crowd-based game on the first series of Channel 4's Gadget Man with Stephen Fry and Librarygame, a Library gamification platform for Universities. Librarygame is being played by over 6,000 students at The Open University, The University of Manchester, The University of Glasgow and The University of Huddersfield.

In my spare time I enjoy long distance running, watching all sports (especially F1) and playing video games. I live in the Holme Valley in West Yorkshire with my wife, Alex.

Sometimes I tweet.

  • Pingback: Posting data from a PhoneGap app to a server using jQuery()

  • jb

    That’s nice, but what about when you have radio buttons?  You want a label for the radio buttons as a group, but probably also one label per radio button (for example ‘Gender’).

  • jb

    Sorry – ignore my comment :)  I hadn’t read far enough :)

  • Hi JB,

    This is covered towards the end. I kind of just glossed over it. I’ll make it a bit clearer :) Thanks for pointing it out!

  • No problem. I didn’t make it very clear :o

  • jb

    Thanks Sam.  I really like the article and am going to put it to use in a site I’m building right now so any clarification would be much appreciated.  Keep up the great work writing articles like this – it’s really nice and clear with a good example (that I would have found if I’d read far enough in the first place!).

  • Thanks, that’s great to hear! 

    I used to loathe marking up forms and styling them, but since I’ve adopted this simple approach I’ve managed to keep them much more manageable. It’s a nice slice of re-usable code.

  • Thx, Sam! This helped me today.

  • Glad you found it useful :)

  • why do you not use div in form? P is for paragraph, div is for unnamed parts of layouts.

    ….

  • I haven’t used a p tag in this technique.

    https://gist.github.com/4344830.git

  • Michael Packer

    I’m curious how you might handle a form where multiple labels are associated with the input control, such as an error. Associating the error directly to the form field where the error has occurred is sometimes used as an accessibility solution.

  • ank

    HI sam,

    when i submit the button it takes only two qury string comment and email and it dosnt take data-landmark-id and append the new url with old one please give me solution

  • ank

    hi sam,

    i am attaching image which type of error i am getting.and please check url it append new url with old one when i click on submit

  • Hi ank,

    data-landmark-id? I’m not sure what you are referrig to?

  • S.P.Balamurugan

    Hi,

    What is the use of display: block for the b tag ? i don’t think it is needed.

  • The b element is inline by default and must be set to block to have its width value set.

  • S.P.Balamurugan

    Thanks Sam for your reply. I understand that. But, even though i remove the display:block property via firebug the output remains the same. Hence the doubt. Kindly check it. Thanks again for this useful post.

  • verlok

    The “b” tag is inappropriate there. It means “stylistically offset text”. We sould use a different tag, why not use a meaningless tag, like a “span”, given that you are inside a label?