3

So I'v seen many tutorials and still haven't come up with a cohesive answer to this question: What's the correct/best way to mark up a form where I have a logical grouping of elements consisting of a label, control (input or select), and previous value, i.e. a single field?

I would like the CSS layout to place each grouping on a new horizontal line.

I've seen <div> wrappers, <br> tags, <ul>, <fieldset>, <tr>, and nothing at all (i.e. no markup tag, only CSS) used for this purpose.

Tables, aside from having a bad rep for doing form layout, aren't very flexible when the format of a row needs to vary. And br seems like a horrible idea (even though I've seen it in tutorials). I'm already using fieldset to create logical groupings of fields in a form, but I could always use two different classes if it's more semantically correct than div. The ul approach seems to be common by weird... the outer fieldset groups multiple fields, why do I need a ul that also groups them?

I really like the simplicity of the markup in this design: http://woork.blogspot.com/2008/06/clean-and-pure-css-form-design.html. But I'm having difficultly adapting the CSS to handle more complex fields, e.g. a select and input that logically belong together.

So in this example, what (if anything) to I wrap around field #1 and field #2 below?

<form .....>
  <fieldset> <legend>Group 1</legend>

    <!-- 'field #1' -->
    <label for="newName">Name</label>
    <input type="text" id="newName">
    <!-- oldVal Filled in with Javascript or server-side script -->
    <span class="oldVal" id="oldName">Old Name</span>

    <!-- 'field #2' -->
    <label for="newFood">Favorite Food</label>
    <select id="newFood">
      <option value="pizza">Pizza</option>
      <option value="tacos">Tacos</option>
      <option value="other">Other</option>
    </select>
    <input type="text" id="newFoodOther"> <!-- type here when 'other' is selected -->
    <span class="oldVal" id="oldFood">Pizza</span>

  </fieldset>
  <fieldset> <legend> Group 2</legend>
    <!-- more fields here -->
  </fieldset>
</form>

What's the easiest to use for controlling the form layout, and what's the most semantically correct? And am I fortunate enough to have those be one and the same?

Khadija
  • 310
  • 1
  • 9
Brian McFarland
  • 9,052
  • 6
  • 38
  • 56
  • If you've not seen the way Twitter Bootstrap handles forms, it's worth looking at: http://twitter.github.com/bootstrap/#forms. Keep in mind that this will change in version 2 of Bootstrap. – Josh Smith Dec 27 '11 at 16:33
  • 2
    Just use a div. http://coding.smashingmagazine.com/2011/11/11/our-pointless-pursuit-of-semantic-value/ – John Stimac Dec 27 '11 at 16:38
  • @Jcubed The div approach seems to have the added value of making the form readable if CSS is disabled for whatever that's worth. – Brian McFarland Dec 27 '11 at 17:52

2 Answers2

3

There is no single correct way to semantically mark up a form. Some methods are more flexible than others, but that doesn't mean you should choose them all the time. Sometimes a bit of quick markup is best.

For flexibility, I typically use a structure as follows:

<form>
    <fieldset>
        <legend></legend> <!-- optional -->
        <label>
            <span>Label Text</span>
            <input type="..." />
        </label>
        <!-- repeat -->
        <input type="submit" ... />
    </fieldset>
</form>

Alternatively to help style with CSS I might use multiple labels:

<form>
    <fieldset>
        <label for="some-id-0">Label Text</label>
        <label class="text-label">
            <input type="text" id="some-id-0" />
        </label>
        <label for="some-id-1">Label Text</label>
        <label class="password-label">
            <input type="password" id="some-id-1" />
        </label>
    </fieldset>
</form>

But then I could separate this out into a list:

<form>
    <fieldset>
        <dl>
            <dt>
                <label for="some-id-0">Label Text</label>
            </dt>
            <dd>
                <label class="text-label">
                    <input type="text" id="some-id-0" />
                </label>
            </dd>
            <dt>
                <label for="some-id-1">Label Text</label>
            </dt>
            <dd>
                <label class="password-label">
                    <input type="password" id="some-id-1" />
                </label>
            </dd>
        </dl>
    </fieldset>
</form>

I find that adding more generic structural elements and classes tends to add flexibility to a certain degree, however you wont need any of that structure if you simply want a mad-lib form:

<form>
    <p>
        Hi, my
        <label for="fullName">name</label>
        is
        <input type="text" id="fullName" name="fullName" placeholder="Full name" />
        and I would like to request a copy of
        <select id="publication" name="publication">
            <option>Super Awesome Newsletter</option>
            <option>Even more awesome-er newsletter</option>
            <option>Lorem Ipsum weekly</option>
        </select>
        please send it to
        <input type="temail" id="email" name="email" placeholder="email@example.com" />
    </p>
    <input type="submit" value="Thank you!" />
</form>

In the end the semantics revolve around how you want the form read. Unfortunately that means restructuring the form if significant changes are made.

zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • The first method where everything is a child of label only works if you only have one input associated with a field/display row. Why would you use a label to aid presentation of an element that is clearly not a label as done in the second example? – Brian McFarland Dec 27 '11 at 19:00
  • @BrianMcFarland, i typically add a `[title]` to the ` – zzzzBov Dec 27 '11 at 19:05
  • Is there an accessibility issue caused by `
    `? I believe a `for` attribute can be used to direct focus to any element upon clicking a label, unless there are issues with crappy browsers.
    – Brian McFarland Dec 27 '11 at 19:42
  • @BrianMcFarland, If you remove all styles from `` and set it to have `100%` width and height, you can style the `label` to look like the text field. If you use a div, and someone clicks on the div, the input element doesn't gain focus, but if you use a `label` it sends focus to the input element. It's very helpful for getting a consistent cross-browser styling, or fluid-width input elements. – zzzzBov Dec 27 '11 at 19:48
  • Guess I see what you meaning about clicking on the div now. Example: http://jsfiddle.net/6CyTv/. Still failing to grasp how they scale differently or for that matter why you wouldn't just style ``. – Brian McFarland Dec 27 '11 at 20:25
  • @BrianMcFarland, it's helpful for styling [flexible input areas](http://jsfiddle.net/h4aJr/) that fill their containers while maintaining borders, margins and padding. It's overkill if you plan on having static-width form fields set using `[size]`. I consider it to be one of the many tools in my web-development toolbox, but you have to use the right tool for the right job. – zzzzBov Dec 27 '11 at 20:44
  • I just learned [why styling the label overflows the container](http://stackoverflow.com/questions/628500/can-i-stop-100-width-text-boxes-from-extending-beyond-their-containers) . It makes me want to cry. Well thanks for your informative comments! – Brian McFarland Dec 27 '11 at 22:02
0

"Semantically correct" applies to the HTML, not the CSS, and I'd say you already have that covered.

There's an infinite number of ways to style the form, of course, but one thing you can do without adding any extra markup is to make the labels into one "column" and the inputs into another:

label {
    display: block;
    float: left;
    clear: left;
    width: 150px;
}
input, select {
    display: block;
    float: left;
    width: 150px;
}

http://jsfiddle.net/mblase75/ECmwH/

This leaves the problem of where to display your "oldVal" fields, but I think that's a matter of opinion.

Blazemonger
  • 90,923
  • 26
  • 142
  • 180