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
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
An <input>
of type password behaves exactly the same as a text input, except that whatever you type in it is obscured.
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:
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:
(This is true for desktop browsers anyway. Most mobile browsers don’t do this yet.)
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).
Again, desktop browsers validate these automatically:
Phone number
The tel <input>
type, as we saw in the previous post, gives you a phone keypad on smartphones:
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:
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:
You can set minimum and/or maximum values, and a step size. These affect the behavior of those spinner controls.
Autosuggest
Empty:
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
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
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
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:
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:
Open:
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
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
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:
You can see the code for that here.
You can also combine an input with a button to get this:
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
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.
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
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:
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?
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.
brilliant! thank you. this is just what the doctor ordered. cheers mate.
Pretty easy to follow. Thank you and thank you!
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.
This is part II, where can I find part I ?
I’m stupid It’s here : http://livetyping.capcloud.com/blog/forms-the-compleat-guide-part-1-layout-and-alignment.html
Great article, good for my eyes and skills pocket. I have been looking for some material like this for a long time. Cheers!
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.
I’m using webshims .. Let’s you change out the date pickers.
– 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. 😉
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. 🙂 )
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.