Form markup challenge

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

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:

Image credits: Brad Frost

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 -->

    <legend>Choose an amount to donate</legend>
        <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>
    <label for="is-monthly"><input type="checkbox" id="is-monthly" />I would like to make this a monthly donation</label>

<!-- 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 <label>, the <input> being preferable, IMO. The phrase stored in it will replace the text in the <legend> dynamically when a user hovers or chooses an option if they have Javascript enabled of course.

That’s it, there won’t be the “styled” version. Both Thierry and Brad did that and they did that marvelously. Feel free to express your opinion on my variant.

  • Hi Alex,

    I think radio buttons *should* be wrapped in their own fieldset (as I did in my example), and that’s not just me saying this [1]. Also, “legend” is announced (by screen-readers) with every control inside the fieldset, so wrapping the checkbox in it makes things confusing as that option is not an amount to choose from, as suggested by the legend: “Choose an amount to donate”.

    Lastly, as your demo shows, the value of the @title attributes is not accessible to all users even though it is said to help donations, which should be the ultimate goal of this form.



    • Hey Thierry, thanks for the feedback.

      It happens so, that I’ve been thinking exactly the same thing as to include the checkbox into the fieldset or not. As far as I understand your opinion it should not be included because the legend says to choose and a checkbox is not an option. Let me broaden this a bit further, OK? If the legend says “choose an amount to donate” – you include only the radio inputs. If the legend said “donation amount” – you would have included the input[type=number] into it, and if the legend said “donation details” – you would have included the checkbox too. Is that correct? If yes, then I disagree with it. Do you really think that <legend>‘s text has that tremendous power to control what should be included in the <fieldset>? Especially given the fact that the <legend> element is optional now?

      I love the idea you follow Paciello Group. In fact, I read them too :) Although I would not expect a 7-year-old article to hold true today in terms of “how screen readers deal with pronouncing the <legend>“. Even if we accept the fact that <legend> may be announced before each field then I guess we are all screwed. Because even in the case of Personal info, having screen readers pronounce “Personal info name”, “Personal info age”, “Personal info sex” is damn wrong.

      Why do you think the title is not accessible? I may have written it not clearly enough, but the final result should be Brad’s, where the text from the title replaces the text in the <legend>. Just the way the gif in the article shows. Please, elaborate on it.

      Lastly, let me thank you once again, it’s always a pleasure to dig to the most excellent and accessible version, though I mostly try to do that on my own :)

      • Regarding legend/fieldset: if you have a Mac you can try Voice Over. You’ll see that it will announce the legend *after* the labels. Yes – after – not before. This is a fact, and we need to deal with it. It has nothing to do with our personal preferences or what makes sense to us as authors.

        Regarding @title: it is not accessible to sighted keyboard users and to screen-reader users (depending on their settings or on which element it is applied to).

        Give your example a try in Voice Over or NVDA, you’ll see where it falls short accessibility wise.

        Thank you.