Brad Frost started it. He shared with the community his way of making an effective donate form. It was caught on by Thierry Koblentz who suggested some clever things to improve it and passed it on to me. And now it’s my turn of the challenge (I promise I won’t nominate anyone :) ). I’ve got several things that haven’t been shown yet.
The task is fairly simple. To markup a part of a form that deals with the amount of money a user wishes to donate. Like so:
I am not going to compare the two previous versions against one another, I’m just going to present my own variant and try to explain why I find it good.
<!-- step 1 --> <fieldset> <legend>Choose an amount to donate</legend> <div> <input type="radio" name="amount" id="donate25" value="25" title="$25 can feed a family for a day" /> <label for="donate25">$25</label> <input type="radio" name="amount" id="donate50" value="50" title="$50 can feed a family for a week" /> <label for="donate50">$50</label> <input type="radio" name="amount" id="donate100" value="100" title="$100 can feed a family of 4 for a week" /> <label for="donate100">$100</label> <input type="radio" name="amount" id="donate250" value="250" title="$250 can feed a family of 4 for two weeks" /> <label for="donate250">$250</label> <input type="radio" name="amount" id="donate500" value="500" title="$500 can feed a family of 4 for four weeks" /> <label for="donate500">$500</label> <input type="number" name="amount" id="other-amount" title="Every dollar you donate helps end hunger" /> <label for="other-amount">$ Other</label> </div> <label for="is-monthly"><input type="checkbox" id="is-monthly" />I would like to make this a monthly donation</label> </fieldset> <!-- step 3 --> <button type="submit">Submit</button>
The unstyled POSH variant can be seen here.
What’s going on here
The donate form consists of three logical groups of controls: an amount to donate, personal info and billing information. We know just the tag that helps group several form controls under one title. It’s the
<fieldset> (the title being the
<legend> element, of course). This element is sort of
<section> but for form controls. Interestingly in the HTML5 specification the
<legend> element is optional, we’ll get to that in a minute.
Now. About that div-thing in the middle. Are there any better options here?
Well, that looks like a list of options to choose from – this is probably the first thing that comes to a developer’s mind. Is it ordered or unordered? Looks like we have some sort of order here, at least we show values from lowest to highest until we see the regular input.
But we can change the order to this, for instance, 500, 25, 50, 100, the meaning of the list itself will not change, it’s still a choice of options, be it quite a strange one. A
<ul> then? I kinda dislike it too, in my opinion it just feels wrong… in other words – I’m not sure, and when in doubt, I prefer to use something that won’t hurt. Because using an unsemantic wrapper is far better than using a semantic one wrong.
I’ve just written above that a
<fieldset> no longer requires any
<legend> to be present, so can we simply use that instead of a
<div>? To show they form an inner group inside a group. My guess is “no”. Reasoning: the main
<fieldset> does exactly that and has a proper
<legend> for it. I would use the nested
<fieldset> only in the third step where we can wrap all the different input fields connected with the credit card credentials thus forming an inner
<fieldset>. Because IMHO in order to form a group worthy of its own
<fieldset> the form controls have to deal with different parts of a common field. Like a name, surname, sex, age do to be fieldseted under the “Personal information” legend.
A user is supposed to choose one option only and that’s definitely a place for
<input type="radio">. No need to explain that I guess.
Also I use the
title attribute to store the additional information that is important for the user. There are two options here: we can have this attribute either on the
<input> or the
<input> being preferable, IMO. The phrase stored in it will replace the text in the