Forms: The Complete Guide–Part 2

Posted by

Forms are one of the most important parts of any site or app—they are the most common way for our users to give us the information that we need to help them do what they want to do.

But in many instances, we design forms statically, often as wireframes. But so often, what makes or breaks a form is what it’s like to interact with it. When the user clicks on a particular radio button, some additional inputs appear. How does that happen? More importantly, does the user understand what just happened?

Things like this are next to impossible to explore using static deliverables. But with a prototype of a form, it’s easy. And with a prototype form made in HTML, you can make it look and behave exactly like the real thing. Which means that once you’ve validated it with users, you can be sure that it can be implemented so that the appearance and feel are just the same.

This series does not try to explain what your form should contain, how the fields should be grouped and laid out, where to put primary and secondary buttons, and so on. There are lots of great resources out there that do that already. (Like Luke’s and Caroline and Gerry’s books. Or Justin’s article.)

No. What this series does is give you the how. You’ve already figured out what you think your form should contain and how it should behave. These posts will give you everything you need to know to make a prototype of your form in HTML, something that looks, works, and feels like the real thing. Which you can then use for usability testing, for getting stakeholder buy-in, and as a living specification for developers.

In the first post in this series, I showed you how to lay out a form and align the labels the way you want, using HTML and Foundation.

In this post, I’ll show you the different types of inputs available to you and how to use them.

To make the most of this post, I strongly encourage you to get your hands dirty by actually typing in the examples and then opening them in your browser to see how they look and work. From personal experience, this gets it into your brain, into your fingers, much better than just copying and pasting.

Input types

There are several different HTML elements that are used in forms. Buttons get their own element (<button>), as do drop-down lists (<select> and <option>), and multi-line text inputs (<textarea>).

But most form elements are the <input> element, with a type attribute that specifies what kind of input it is.

Let’s look at them one by one.

If you’re following along and actually typing this stuff in, you need to set up a new Foundation project, open up its index.html file, and delete all the sample content (see this post to find out how).

Then add an empty <form> element and the necessary Foundation layout elements.

Once you’ve got that set up, you can just add each example within the <fieldset> tags, after the <legend> element.

Note: In the code samples below, you’ll notice that all the <input> elements have both a name and an id. Why is this? It’s because you need the id to be able to identify individual HTML elements (to style them with CSS, etc.). But for a real form, you need name so that the data that gets sent to the server will be labeled correctly. These aren’t proper forms, they’re just prototypes. But it’s good to do it properly from the start. So the rule of thumb is: for <input>s, use both id and name, and give them both the same value. (An exception is radio buttons—I explain why they’re different below.)

Text and its variants

Text

Type some text

An <input> of type text is just a simple input field. There are no restrictions on what the user can type in it (though there are attributes that you can add to do things like limit the length of the field’s contents—see below).

Password

Password

An <input> of type password behaves exactly the same as a text input, except that whatever you type in it is obscured.

Email

Email address

An <input> of type email is the same as a text input, except that on phones and tablets, the keyboard that is displayed has @ and dot keys as standard—you don’t have to go digging for them:

Keyboard displayed based on attribute
Keyboard displayed based on attribute

It also gives you validation for free. If you enter something other than a valid email address and then submit the form, the browser will do something like this:

Invalid email address notification

(This is true for desktop browsers anyway. Most mobile browsers don’t do this yet.)

URL

URL

The url <input> type is similar to email, except here you get a keyboard layout with slash and dot keys (and maybe others, such as .com).

Keyboard displayed based on attribute
Keyboard displayed based on attribute

Again, desktop browsers validate these automatically:

Invalid URL

Phone number

Phone number

The tel <input> type, as we saw in the previous post, gives you a phone keypad on smartphones:

Keyboard displayed based on attribute
Keyboard displayed based on attribute

Number

Number

The number <input> type doesn’t restrict what you can type, but on smartphones (the iPhone, at least), you get the regular keyboard, switched to numbers-and-symbols mode:

Keyboard displayed based on attribute
Keyboard displayed based on attribute

Different desktop browsers render this input differently. In IE and Firefox, it looks the same as a text input, but in Chrome and Safari, it gets spinner controls for increasing and decreasing the value:

Spinner

You can set minimum and/or maximum values, and a step size. These affect the behavior of those spinner controls.

Autosuggest

Empty:

Empty autosuggest

Typing:

Autosuggest while typing

You can use an <input> with a list attribute paired with a <datalist> element to get something that is kind of a cross between a text input and a drop-down list. As you type in the input, a dropdown list shows you matching options. You can click on an option or use the arrow keys and Enter to select.

Other types

There are a number of other <input> types that were introduced with HTML5, but most of them are not widely supported yet. These include color and various date and time inputs, such as date, time, datetime, datetime-local, week, and month.

For now, you’re better off using things like the jQuery Datepicker.

The rest

Checkboxes

Checkboxes

If you give an <input> a type of checkbox, you get a checkbox. These usually have their label to the right. For checkboxes, the for attribute is particularly important—it makes the label clickable—clicking it is just like clicking the checkbox itself. Adding the checked attribute (which doesn’t take an argument) makes the checkbox checked when the page loads. For a prototype it doesn’t really matter, but a checkbox in a real form must have a value attribute.

Radio buttons

Radio buttons

Like checkboxes, with <input>s of type radio, the label usually comes after the input. And for and checked work the same here too. Here though, be sure to give all the radio buttons in a group the same name attribute—this tells the browser that they belong together, and that only one can be selected at a time. Again, like with checkboxes, every radio button must have a value.

Sliders

Sliders

An <input> of type range gives you a slider. Like with number, you can specify a minimum, maximum, and step values. But this control is not hugely useful on its own—if precision is not an issue, you can probably get away with just adding text before and after the <input> to show the maximum and minimum values. But in most cases, you’ll probably want to provide some sort of feedback so the user knows what value they have selected.

This is not difficult. It requires a tiny bit of Javascript, but you’ll see in a minute that it’s really no big deal. We just need to take the existing bit of HTML and add an <output> element to show the value. And we add an oninput attribute to the <input> to tell it what to do when its value changes.

In this version, the <input> and <output> elements are in separate columns, and I’ve given the <input> a width of 100% so it will stretch to fill its column:

Slider with indicator

The little bit of Javascript that is the value of oninput just sets the value of the output (range_value.value) to the value of the input (range_input.value). (range_value is the <output>‘s ID, and range_input is the <input>‘s ID. Adding the dot and value just means “the value of the value attribute of the element with this ID.”)

Drop-down lists

Closed:

Closed dropdown list

Open:

Open dropdown list

Drop-down lists are not <input> elements—they are made up of a <select> element containing a number of <option> elements.

This is fairly straightforward. One thing I’ve added here though is the first <option>—it prompts the user what to do, but is not actually an option they can select. (The selected attribute means it is what is displayed in the closed dropdown before the user interacts with it.)

Without this option, “Option 1” would be selected by default. Usually we don’t want anything to be selected by default.

Textareas

Textarea

A <textarea> is like a text <input>, except it lets you enter multiple lines of text. Like all the text-like <input>s, its width is 100% of the column that it’s in.

As for height, there are two ways to set this. One way is to set the height in CSS (or directly on the element by adding a style attribute). The other way is to use the rows attribute, like I’m doing here. This makes the <textarea> tall enough to fit six lines of text.

(The style="height: auto;" attribute is to get around a bug in Foundation. If you set the height to a specific value instead of using rows, you won’t need this.)

Buttons

Buttons

Most forms have buttons that you have to click to send the information you’ve entered to the server. Some also have a button for a secondary action, to cancel out or to reset the form (though some argue that such secondary actions are usually a bad idea).

Here, the buttons are <input>s of type submit and button. (submit is a special kind of button for submitting a form.) The right place to put these is after the closing </fieldset> tag.

The Submit button gets a class of button to make it into a nice-looking Foundation button, while the Cancel button also gets a class of secondary to make it visually less prominent.

Foundation also lets you use the <a> element for making buttons—just give it a class of button. It also lets you do stuff like make buttons smaller, give them rounded corners, and so on, just by adding classes.

Other clever Foundation stuff

Foundation lets you do some clever things that the standard HTML elements don’t let you do.

For example, you can combine an input with a label to get something like this:

Input and label

You can see the code for that here.

You can also combine an input with a button to get this:

Input with button

The code for that one is here.

Important attributes

I mentioned a few attributes along the way, like id and name, checked for checkboxes and radio buttons, min, max, and step for number and range type inputs, and so on. But there are some others that you need to know about.

autocomplete

Browsers try to help us by automatically filling in form fields for us when they can. But sometimes this is not appropriate, for example, for sensitive information such as bank account and credit card numbers (and even passwords in certain cases, though beware of being annoying with this one).

Setting autocomplete to off for an input tells the browser not to fill it in automatically.

autofocus

On each page, you can give one (and only one) form control the autofocus attribute. This field will get focus when the page loads, so the user can start interacting with it without having to click in it or tab to it.

disabled

Disabled

A control with the disabled attribute gets greyed out and you can’t interact with it. This may be because it’s not relevant unless some other control has a particular value. (For example, if your form has a “How did you hear about us” section with radio buttons, the last one might be “Other”, with a text input so the user can type something that’s not in your list. It makes sense to make this input disabled unless “Other” is selected. I’ll cover this sort of thing in more depth in a subsequent post.)

maxlength

Text-type inputs (text, email, url, tel, etc.) can have a maxlength attribute. This lets you specify the maximum length in characters. Most browsers won’t let you type any more once you hit the limit. This is handy for things like phone numbers, which can’t be longer than a certain number of digits.

multiple

The <select> element and <input>s of type email (also of type file, for uploading files, which I haven’t covered here) can take the multiple attribute. This lets you select multiple items in a dropdown or specify multiple email addresses, respectively.

Select multiple

Notice how the <select> is displayed differently when multiple selection is enabled.

pattern

pattern tells the browser what an acceptable value looks like. I’ll cover this in a subsequent post when I talk about validation.

placeholder

Placeholder

The placeholder attribute puts hint text inside the <input> (or <textarea>), to give the user an idea of what they need to type. It disappears when you click in the <input>. Some sites use it to indicate which fields are mandatory and which are optional.

IMPORTANT: Do NOT use this instead of a <label>. It is very bad from both accessibility and usability points of view.

required

The required attribute means that a field is mandatory. It doesn’t change its appearance (an asterisk doesn’t magically appear next to its label), but if you submit the form without filling it in, you’ll get a helpful message:

Required field

tabindex

The tabindex attribute (which has a numerical value) determines the order in which controls get focus when the user presses the Tab key.

If you’re doing something weird with your form layout such that the inputs are in a different order on the screen than in the page source, you should use the tabindex attribute to make sure that focus jumps to the right input when the user tabs between them.

Special considerations

On phones and tablets, there are additional challenges that we face. How often have you come to sign in or register at a site on your phone and seen something like this?

Autocorrect fail

On m.hpdirect.com, as I’m typing in the User ID field in the login form, my phone is automatically capitalizing the first letter and wants to correct what I’m typing to words it has in its dictionary. So now I have to tap the little “x” to dismiss autocorrect, and go back and change the capital “M” to a lowercase one. Grrr.

For fields like this, there are two attributes that we can add to turn off this antisocial behavior: autocorrect and autocapitalize.

They both take the same values: on and off. By default, they are on.

Conclusion

Hopefully you now have a pretty good idea of the building blocks that you can use to create your prototype forms.

In the next post, I’ll show you how to group inputs into logical (and less overwhelming-looking) groups and how to provide help to users while they are filling in the form.

13 comments

  1. Great article…thanks. There’s certainly a lot to be excited about with the newer input types and their attributes. At the same time browser support is lacking and those that do support the types take total control over the controls/widgets they provide to assist with input.

    Just look at Roger Johansson’s HTML5 input types test page at http://www.456bereastreet.com/lab/html5-input-types/ in Chrome and Firefox (I’m using latest versions on a Mac). Even before interacting you’ll see many differences.

    Chrome modifies the look of many inputs based on type: search inputs have rounded corners, number inputs are less wide, date/month/week/time/datetime get automatic placeholder text, and color input is recognized. If you want to change the search input border radius, for example, you’ll need to use the browser-prefix property -webkit-appearance (setting border-radius will have no effect as long as -webkit-appearance equals “searchfield”.

    Once you start interacting you’ll see the real differences. Chrome gives you a datepicker for the various date related fields, inserts an “x” icon to clear the search input, adds both an “x” and an incremental control for time, and an incremental control for numbers, and a color picker for color inputs. Firefox does none of those things.

    Enter a non-URL in the URL field and submit in both browsers. The browser generates an error message and tooltip, and that’s great, but they’re vastly different in the two browsers and you’re given no design control over them (the same goes for all browser input controls).

    It’s a fair argument to suggest the benefits of letting the browser assist us with forms is worth some design sacrifice, but try telling that to companies that spend a lot of money and time branding and designing the user experience, not to mention messaging. And it can be a bit jarring for a user to see the global error/tip messaging styling you use throughout your site on other form inputs and then see these seemingly disparate browser-controlled controls or errors.

    And even if you’re okay with all of that, for now you still have to write code to compensate for browsers with different or incomplete implementations of these features.

    For mobile/touch devices the newer input types are awesome–you can’t beat context-aware keyboards, for example. But even when these inputs and attributes are finally fully supported by browsers I’m not sure the designers and UI people I work with will accept the lack of ability to determine style and message.

  2. Great article, good for my eyes and skills pocket. I have been looking for some material like this for a long time. Cheers!

  3. Thanks for your kind words, folks 🙂

    @Junior: It’s always a pleasure when someone chips in who knows more than me. I wasn’t aware of all the specifics of the different ways that different browsers render this stuff. Thanks for broadening my knowledge 🙂

    For sure, the closer you get to production, the more this stuff matters. For earlier stages of design though, I think there’s more good than bad here. Especially when you have control over how you show your prototype form to clients/stakeholders/developers/whoever (in terms of the browsers/devices you use).

    But as the process moves forwards, we must, as you point out, have our finger on the pulse to make sure the browser differences get accounted for.

  4. – Your markup suffers from divitis and is not semantic.

    – Self-declared “professional” frameworks like Foundation teach people (like you, apparently) to forget about semantics and use 19 CSS classes per line of HTML. We fought so hard to get over that and now it’s all back. Using and <a> for buttons, come on….

    – Things like “Select…” should be optgroups, not disabled options.

    – Why close fields? (except for the very first one?)

    Sorry if this sounds harsh, I’m just passionate about this topic. 😉

  5. Hey Skythe,

    Thanks for the feedback!

    I hear what you’re saying. Frameworks like Foundation and Bootstrap do add weight, both in terms of the size and number of files that they add and in terms of the additional markup that you need to add. Plus those 19 class names of course…

    But they do let you lay out forms (and pages in general) quite quickly and easily. Which for a prototype (which may, or even should, be discarded) is a good thing.

    Anything that lets you create a prototype form quickly so you can get it in front of real users earlier so you can see if they can understand it is a win, IMO.

    Whether the same is true for a production form/site is a different argument. 🙂

    (As for the other criticisms, they’re valid. As for closing the <input> tags, I blame my chosen text editor, which closes tags automatically. 🙂 )

  6. For accessibility, it may be better to use button elements in place of input elements with a type of button or submit. If you have a case against this I’d be interested in hearing it, but generally speaking anything that will be a button should be a button element, so also adding a ‘button’ class to other elements seems like a bad idea.

Comments are closed.