Forms are forms, not lists

Respecting someone or their publication does not prevent one from disagreeing with them. In fact, I think to nod along saying “you’re so right, OMG, you are so right!” is less respectful than listening to and considering what they say. That dealt with, allow me to disagree with some people I respect.

Frequently, I see HTML forms coded as lists. I’ve seen this in code by some publications and people I highly respect, such as on A List Apart. The code may be:

<form action="example.php" method="post">
<ol>
  <li>
    <label for="itemOne">Item One</label>
    <input id="itemOne" name="itemOne" />
  </li>
  <li>
    <label for="itemTwo">Item Two</label>
    <input id="itemTwo" name="itemTwo" />
  </li>
</ol>
</form>

The method remains much the same if using unordered or definition lists. The argument for using this method is that forms are a list of fields. A variation is to use a table, arguing that forms are a table of labels and inputs.

I don’t believe either argument is correct, I believe forms are a series of:

  • fieldsets;
  • legends;
  • labels;
  • buttons;
  • inputs, selects, options, etc.

All semantic meaning for forms should come from the appropriate HTML tags. If you want to use other elements as hooks for styling, they should be semantically meaningless spans and divs.

I consider the arguments cited above as justifications for making styling easier. Without block elements, forms can be difficult to style. Rather than wrapping each input pair with a list item, I wrap them with divs.

<form action="example.php" method="post">
<div>
  <label for="itemOne">Item One</label>
  <input id="itemOne" name="itemOne" />
</div>
</form>

Wrapping each input pair in a div is just as lazy as wrapping each input pair in a list item. However, as divs are meaningless, it doesn’t require bending of semantics to justify my actions.

There is a valid argument for an element to define an input pair but I think such an element is redundant. We already have a method for defining the pairing of labels with their inputs. The “for” attribute within the label pairs with the “id” attribute of the associated input.

If you wrap your forms in a list or a table, look carefully at what you are doing. Ask yourself; is what you are doing semantically valid or are you lazily trying to make styling easier? As context for your consideration, ask yourself if a whole page of text is really just a list of paragraphs.

Published by Peter Wilson

Peter Wilson is a Senior WordPress Engineer at Human Made and contributor to WordPress core. Peter has worked on the web for twenty years on everything from table based layouts in the 90s to enterprise grade CMS development. Peter’s a big fan of musical theater and often encourages his WordPress community colleagues to join him for a show or two in New York or in the West End.