preview

20+ HTML Forms Best Practices for Beginners

Working with XHTML forms can be somewhat daunting; they not only use some niche HTML elements, but also blur the line between static content and user interaction. Let’s review some things to remember when creating your next form.

Good HTML forms require attention on at least four points:

  1. Semantics
  2. Accessibility
  3. Functionality
  4. Design

Forms can be difficult and sometimes even annoying for users;
often, a form interrupts a user’s main focus and direction on a page:
they’re intent on purchasing that gift, or trying out your new web app,
not giving you their shipping address or coming up with yet another password.
These tips will make forms easier for you as a developer/designer, and
them as a user.

Semantics

1 : Use fieldsets to encapsulate similar fields

Generally, forms are made up of inputs inside form tags. When you’ve
got a lot of fields that the user must fill out, it can be easier for
both the user and you, the developer, to keep track of input by using
fieldsets. The perennial example of this is using fieldsets to separate
a billing address and a shipping address.

<fieldset>
    <span>Billing Address</span><input type="text" />
    <span>City</span><input type="text" />
    <span>Province</span><input type="text" />
    <span>Postal Code</span><input type="text" />
</fieldset>

<fieldset>
    <span>Shipping Address</span><input type="text" />
    <span>City</span><input type="text" />
    <span>Province</span><input type="text" />
    <span>Postal Code</span><input type="text" />
</fieldset>

2 : Label Fieldsets with Legends

It hardly makes sense to use a fieldset without giving it a clear name.
We can improve the code above by using the legend element to title our
fieldsets. The fieldset element has a border by default, and the legend
will lay itself over that border.

<fieldset>
    <legend>Billing Address</legend>
    <span>Address</span><input type="text" />
    <span>City</span><input type="text" />
    <span>Province</span><input type="text" />
    <span>Postal Code</span><input type="text" />
</fieldset>

This results in the following:

legend

3 : Name your Inputs

If you want to pass form data to a script, each input element needs
to have a name; if you are using PHP, these names will become the keys
to a super global array, usually $_POST or $_GET.

<fieldset>
    <span>Billing Address</span><input type="text" name="billAddress" />
    <span>City</span><input type="text" name="billCity" />
    <span>Province</span><input type="text" name="billProvince" />
    <span>Postal Code</span><input type="text" name="billPC" />
</fieldset>

4 : Use the Label Element

Let’s continue improving that code; there’s nothing inherently wrong
with using a span to label the inputs, but the label tag is a born match for inputs.

<fieldset>
    <legend>Billing Affress</legend>
    <label>Address</label><input type="text" name="billAddress" />
    <label>City</label><input type="text" name="billCity" />
    <label>Province</label><input type="text" name="billProvince" />
    <label>Postal Code</label><input type="text" name="billPC" />
</fieldset>

5 : Give Labels the For Attribute

I really like the ‘for’ attribute; it provides a way to bind a label to an
input. The value of ‘for’ should be the same as the id of the input you want
to bind it to.

<fieldset>
    <legend>Billing Affress</legend>
    <label for="billAddress">Address</label><input type="text" id="billAddress" name="billAddress" />
    <label for="billCity">City</label><input type="text" id="billCity" name="billCity" />
    <label for="billProvince">Province</label><input type="text" id="billProvince" name="billProvince" />
    <label for="billPC" >Postal Code</label><input type="text" id="billPC" name="billPC" />
</fieldset>

At first, this is one of those things that only seem to affect your
code’s quality, but they do a special job in the visible content: when
the for attribute is defined, the label becomes a ‘clickable’ area that will
focus the input. For example, clicking the label of a text input will focus
your cursor in the box; clicking the label of a checkbox will check (or uncheck)
the box.

6 : Use optgroup to categorize options

If you have a lot of options in a select, it’s usually better to group
them into optgroups. <optgroup> is a little-known element that will indent
options and give them a title. Note that the label attribute is required.

<select>
<optgroup label="USA">
    <option>Alabama</option>
    <option>Alaska</option>
    <option>Arizona</option>
</optgroup>
<optgroup label="Canada">
    <option>Alberta</option>
    <option>British Columbia</option>
    <option>Manitoba</option>
</optgroup>
</select>

This gives us the following results:

select

7 : Always assign complete attributes

When working with forms particularly, it’s tempting to write like this:

<label for="live">Living?</label>
<input name="live" id="live" type="checkbox" checked disabled />

Yes, this does what it’s supposed to do. No, you shouldn’t code like this!
It isn’t standards-compliant. Whenever you are adding attributes to an element,
don’t cut corners.

<label for="live">Living?</label>
<input name="live" id="live" type="checkbox" checked="checked" disabled="disabled" />

8 : Consider using Buttons instead of Submit Inputs

Generally, <input type=”submit” /> has been the universal submit
button. But HTML has a <button> element. Why would you use it? Well, it’s
generally easier to style buttons; also, you can put images within a button,
so it really offers more flexibility. You can read more in
these
two articles.

Accessibility

9 : Put tabindices on your inputs

It’s definitely easier to tab through a form than it is to use your mouse . . .
however, by default, your user will tab through in the order they are written in
the HTML. If this isn’t the order you want them to go through the inputs, you can
easily add the tabindex property to your inputs; tabindex takes a number value, and will
hop to the input with the next highest value when you hit that tab key.

<input type="text" tabindex="2" />
<input type="text" tabindex="1" />
<input type="text" tabindex="3" />

10 : Define accesskey when appropriate

The accesskey attribute creates a keyboard shortcut that will focus that
input: the shortcut is Alt (Option) + the accesskey value. Obviously, you wouldn’t
put an accesskey on every input, but it would certainly be useful on, for example, a search box.
Don’t forget to let users know about the shortcut; often this is done by underlining
the letter, as it’s usually part of the label.

<label for="search"><span class="shortcut">S</span>earch</label>
<input type="text" name="s" id="search" accesskey="s" /> 

11 : Use good focusing techniques

You could argue that this point is as much on the side of design as it is accessibility.
It’s always nice if a form field (usually a text box, in this case) changes colour when it’s focused, but for the visually
impaired, it’s almost a requirement if they are to use the form successfully.
To this end, you can use the hover psuedoclass in your CSS; this will work in all
common browsers except IE7 and down. You can also use JavaScript for this;
jQuery has a hover
event
.

input[type=text]:hover {
    	background-color:#ffff66;
    	border-color:#999999;
}

12 : Consider people using Screen Readers

Since forms have the tendency to be so tedious, everyone likes a well-designed form.
But don’t let a fancy form ignore screen readers: always make sure your inputs are
clearly labeled. If you don’t want those labels to show (maybe you are labeling text
inputs with values that disappear on focus), you can remove them from the visual presentation
(don’t use display: none, though;
there are better ways
). Also, screen readers generally associate the text directly
before an input to be the label for the input. The exceptions to this are radio
buttons and checkboxes.

Functionality

13 : Use the right Content Type

In most cases you won’t need to put the enctype attribute on your form
tag; it will default to “application/x-www-form-urlencoded.” However,
when you have a file input, which will allow the user to upload the file,
you need to use “multipart/form-data.”

<form action="verify.php" method="get" enctype="multipart/form-data">
    &tl;label for="avatar">Upload your Avatar : </label>
    <input type="file" name="avatar" id="avatar" />
</form>

14 : Know when to use Get and when to use Post

A form can send its data by two methods: get and post; you define
one in the method attribute on the form tag. What’s the difference,
and when should you use them? Ignoring what goes on at the server,
the main difference is the way the browser sends the information.
With get, the form data is send as a query, visible in the url. So
this form . . .

<form action="you.php" method="get">
    &tl;label for="fname">First Name</label>
    <input type="text" name="fname" id="fname" value="Bill" />
    &tl;label for="lname">Last Name</label>
    <input type="text" name="lname" id="lname" value="Gates" />
</form>

. . . would result in this URL when submitted: http://www.example.com/you.php?fname=Bill&lname=Gates

When you use post, the data is sent in the HTTP request header.
That way, it’s not visible to the average user. So which should you
use when? Post is better for sensitive data (like passwords) and any
data that will generally change something (e.g. add a record to
the database). Also, post is your only option if you’re uploading
a file. Get is great for querying the database, and other requests
that don’t have a lasting affect on anything (“idempotent” the spec
calls it). Really, I’ve just scratched the surface on the differences
here: there are
other
articles that go into this in-depth.

15 : Validate on both the Client and Server

validate

Validation is the bane of forms. But it’s best to check the input both on
the client and on the server; validating in the browser allows you to warn
the user of mistakes before they submit the form, which requires one less
transaction with the server. However, always be sure to validate on the server
as well, for security’s sake.

16 : Give your Users Smart Warnings

This goes hand in hand with the previous best practice. Too many times I’ve
submitted a form only to be told “Fields were not filled correctly.” Can you spell
vague? Once you’ve determined that your user has made a mistake, let them know as
soon and as clearly as possible. Put your error messages close to the bad field,
and let your user know what’s wrong with their entry. I like using the jQuery’s blur()
event for this: as soon a user hops to the next box, the previous one is validated.

errors

17 : Consider using AJAX to submit

Many times, submiting a form results in a simple message: “Thank you,” “Check your
email for confirmation,” or “We’ll get back to you when we can.” When that’s the case,
what better place to use AJAX? You could just fade out the form, send the data with
jQuery or (YOUR FAVOURITE LIBRARY), and fade in your message.

ajax

18 : Make sure your form works without Javascript

Maybe this should have gone under accessibility; although the last couple of tips need
JavaScript to work at all, make sure your form is completely functional without them. This means a regular
form submit, server-side validation, and good errors after a page reload.

Design

19 : Style Forms Consistently

I’m no designer, and I don’t pretend to be, but I do know this much: don’t fling your
form fields carelessly around. Your form should be consistent in its styling. Decide whether
your labels will be to the left or right (or perhaps above or below) of the fields, and stick
with it. Make all your text inputs and textareas the same width. Space all your fields equally.
Keep at least one edge of all boxes aligned. The tuts+ comment forms are great examples of well-styled forms.

comments

20 : Consider using JavaScript to Consistently Style Forms over Different Platforms

With upteen browsers/operating system combinations, form element consistency is hardly
possible . . . without the help of a bit of JavaScript. If you want your forms
to look the same on almost every browser, check out the
jqTransform jQuery plugin,
a plugin aimed directly at this compatibility problem. Simply include it, call it, and adjust the included css file
to your taste; it works with IE6+, Safari 2+, Firefox 2+, and Chrome.

21 : Be inspired by others

If you’re having trouble coming up with that unique form design for your site, go for a
little inspiration! Smashing Magazine has a
great roundup of forms,
and Smileycat’s “Elements of Design” Gallery has a bunch of
Blog Comment Forms worth checking out.

Conclusion

22: Look forward to HTML 5 Forms

HTML 5 has some great features for web forms. Two of the most exciting ones are new types
for inputs (like url, email, and date) and the datalist element, which can be used for easy
autocomplete. When these and other parts of the spec get implemented, dynamic forms will be
much easier!

Website forms can be challenging, but I hope these tips will help you make your forms stand
out from the rest. Have a good tip that I didn’t mention? Let’s hear it in the comments!

You Also Might Like


Tags: formshtml
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://www.scottforga.com Brad

    I’m not one to be particular or act like a prick- but I would want someone to tell me. In your step 5 code sample ‘Address’ is mis-typed to read ‘Affress’.

    Great article, and awesome content as always from Nettuts.

    • http://levibuzolic.com/ Levi

      Not only is ‘Address’ misspelled, but a “for” attribute is used on the “input” tag when it should only exist on the “label” tag.

    • Jon Caine

      there always has to be someone who feels the need to state the obvious…as if they’re really “helping” the author or the audience. the guy fat-fingered a coupla letters and didn’t catch it…move on.

      • Marcio Toledo

        Jon Caine, we are talking about a TUTORIAL, if there’s something wrong we need to correct it! Do you think that to come here and say “ohh, lovely tut ^^” is more constructive than asking for a correction?
        ————————————–
        Back to the tut…. I have one to add. Shouldn’t the label tags being encapsulating an input tag? So when the user clicks on the label the browser automatically focus in the input that the label holds…. I think it’s much more logic and semantic. Just my two cents.

        But I like this kind of tutorial, would love to see something about JQuery best pratices too. Thnx

      • Wouter Vervloet

        @Marcio Toledo: That’s what the ‘for’-attribute is for…

        Encapsulating the input is a possibility, but you have way more control over the styling of the label (particularly positioning) if you use the ‘for’-attribute and keep the label separate.

      • http://www.scottforga.com Brad

        I actually specifically referenced that I wasn’t trying to be ugly or anything- I would want someone to point it out to me as a professional in this field if I had been the one who published the tutorial.

    • http://www.davidkendallwebdesign.co.uk DaveK

      Marcio, its blatantly obvious that its a typo, you would have to be brain dead to mistake it otherwise, so pointing it out is a waste of time, besides which it was practically immaterial to the tut. I am all for people pointing out discrepancies as it makes learning easier, but I am also for adults using common sense.

      • Marcio Toledo

        If I was a BEGINNER I would like to be warned in case of errors. “The ‘for’ attribute is used on the ‘input’ tag”, for example. But I don’t want to keep this discussion going, have a good sunday :]

      • Dazle

        The problem with common sense is that it’s not that common.

  • http://www.i-media.lv Matiss Zarkevics

    Very nice article! Taught me a thing or two :)

  • http://www.imblog.info Muhammad Adnan

    Nice Article, i liked it !

  • champ

    Ive read better

  • Alex

    As someone who uses forms like crazy in my web apps, I thought I knew a great deal. But this article was great! I learned so many new things and will definitely be implementing these in the new version of a web site I work on. Thanks so much!

  • Mark Sinkinson

    All common sense and yet so often overlooked by the majority of developers out there.

    I’m pretty heavy on accessibility and if there was one that I would pick that everyone should use, its Labels with a ‘for’ attribute

  • http://www.quizzpot.com crysfel

    Thanks, this is very usefully :D

  • http://www.jlapitan.com jlapitan

    this is great.. more items to share with my students..

  • http://www.d-mueller.de David Müller

    Adding a custom taborder to your form elements can be quite problematic as you will have to change alle tabindex-elements, when you change the order of formelements. It’s always better to design forms in a consistent way and make no use auf tabindex.

  • http://melissa-brandon.com Brandon Hansen

    Not to be picky, but when using label (which you always should), you are also required to have an ID on the form field that it corresponds to.

    It is not actually label for the name, but label for the id.

    • http://11heavens.com/ Caroline Schnapp

      That’s correct. Very important too. The for attribute of the label must match the id attribute of the form field (not its name!).

      • http://andrewburgess.posterous.com Andrew Burgess

        Thanks for pointing that out, guys! I think that’s what I’ve said in point 5; I didn’t have the IDs in point 4 because I hadn’t “introduced” the for attribute yet. But it’s worth clarifying that the for attribute connects to the ID, and not the name.

  • Ant

    You may also use:

    A

    B

    C

    I like this variant better, even though it won’t work in ie 6, but why care of oboslete browsers?

    • Ant

      Sorry, it meant to be:

      <label>A
      <input tabindex=”3″ id=”cb” name=”cb” type=”text” />
      </label>
      <label>B
      <input tabindex=”2″ id=”cb2″ name=”cb” type=”text” />
      </label>
      <label>C
      <input tabindex=”1″ id=”cb3″ name=”cb” type=”text” />
      </label>

    • http://twitter.com/johnathan1707 Johnathan

      Because people still use the browsers and to ignore them would mean you not doing your job properly as a professional. It would actually be pretty stupid to not care for “obsolete” browsers as it;s not obsolete as a lot of people are still using it.

    • Kevin Roberts

      Because users in corporate environments are often forced to use obsolete browsers.

  • faruk

    yes,it usefull for us.

  • Gavin Steele

    Great for beginners!

    Would be cool to have a beginners guide to styling all the elements of the form.
    Thanks

  • Jimbo

    Just though I would ad that the button tag is painful to impalement because it has nasty padding and margin inconsistency’s between different browsers. It requires a lot of extra CSS to fix it. Somethings cant be easily fixed with CSS either! Just go with input for now. It may be less semantic but I think its not worth the trouble in this case. You can also use an image in place of an input button.

    One last thing to note is that input and button behave differently when sending data to the serve. Input can be a little difficult to work with depending on how you use it.

  • http://www.freshclickmedia.com Shane

    Yeah – all good points.

  • canciller

    jajajajajja… I want to post in the point #19, but was an image ..

    silly me :S

    • http://www.alfystudio.com Ahmad Alfy

      LOL that was funny :D

  • http://www.peewee1002.co.uk Peewee1002

    Cheers that is great.

    I just need to put into my design without it srewing up each time.

    All my forms seem to stop working when I add javascript effects to them. – Will have a look at the one you pointed out though as I use Jquery anyway.

  • http://spotdex.com David Moreen

    I wish I had this when I was starting HTML, I had to teach myself! It was still fun.

  • Tracepoint

    There are some good concepts in this article…but there are a couple of really bad ones too.

    You say that there is nothing inherently wrong with using span elements to label form elements, but doing so would cause problems for screenreaders, which contradicts #12.
    Also, IIRC, failing to use labels is a breach of the A standard for WCAG, which, IMHO is an inherent problem.

    #4 is the wrong way to use labels. You’ve corrected this in #5, but still, #4 is not a best practice, in fact, it’s a mistake.

    Tab indices are massively overused and if you’ve designed your form correctly, they shouldn’t be necessary. There is nothing more irritating that loading a website, hitting the tab button and being taken to a random form in the middle of the page. If you’re sighted it’s a mild nuisance, if you’re using a screenreader, it can make the page practically unusable. Using tab index should be an absolute last resort.

  • http://www.pixelgraphics.us Douglas Neiner

    Great post, awesome content. This is a great summary and something I will be referring to.

    I am pretty sure on point 11 that it should be IE6 and lower. In my experience, IE7 supports the :hover attribute on any element.

  • http://www.xitestudiomagazine.com Roberto XSM

    Thanks for the tut and for the useful comments.

  • http://www.onesixtyone.com Kyle Petersen

    Great article–learned a few new things in there myself.

  • Donald Allen

    Awesome article! Some of these commenters are a bit harsh.

  • http://galaxydesign.com.au Sam

    some great new (to me) things in this article eg: optgroup. thanks mate

  • http://www.zarpio.co.nr Khalil

    This is really very helpful for me Thanks

  • http://tuvidaloca.net Rata

    Very good check list, I learned a bit ;)
    Thank you, Andrew.

    Kind regards
    Rata

  • http://bonezdesign.net/ Patrice Poliquin

    Sounds interesting! I’ll give a look when works will be done!

  • http://www.massbase.com/enatom enatom

    the new header with that new ad, takes up half of my screen, on this 15″ laptop.

  • http://htt Joost

    Hi, good topic. Unfortunately these things are often overlooked.
    As for number 11: “you can use the hover psuedoclass “, shouldn’t that be the focus pseudoclass?

  • arnold

    10Qualtiy…
    nice post

  • http://www.maydina.web.id maydina

    Great article…
    I’m a beginner in web design.
    I wanna to learn about CSS more…
    especially in related with blog/web design.
    Can you give a reference to me, where I can learn that?

  • http://www.eshban.com Eshban Bahadur

    Very nice tutorial. Thanks for this.

  • jan

    #8 : Consider using Buttons instead of Submit Inputs

    Can anyone tall me why should I use buttons instead of Submit input, how the variable is passing from the button to the server side script? Is it working the same as Submit?

  • jan

    Found this great comparsion recently and have tried in IE6 the Buttons just do not send the variable to the server side at all:
    http://trevordavis.net/play/input-vs-button/

    Seen this comparsion I would recommed using Submit inpus, at least you will avoid lot of problems

  • http://www.youtubeguy.fr Nanane

    Nice Tuts :)

    Just wanted to tell about image inputs, they become handy when you want to use an image as submit button.

  • http://jacobrask.net Jacob Rask

    Nice roundup. However, in “Always assign complete attributes” you say: “It isn’t standards-compliant” not to add values to attributes. That is not correct. It is perfectly valid HTML, just not valid XHTML.

  • http://www.suburban-glory.com AndyW

    Good article. You’ve made some solid points here.

  • http://webiga.com ilja

    in step 19 u state: “Make all your text inputs and textareas the same width”.

    Not agreeing with it as current usability guidelines state that the field should be as wide as required by its content. A bit of common sense realy, you do not need a telephone number field to be 100 characters long it will be 15 digits at max. Why waste space and confuse users.

    Great round up though. will use some steps from here deff.

  • http://www.dsaportfolio.com.br Diego SA

    You guys have no idea how useful it is. Thanks a lot!

  • Zach

    I’m a noob here, need a little direction.

    When i enter the code in steps 1 and 2, the fields are horizontal across the screen. How do i get them to be formatted vertically as in the example?

    Thanks for helping me out on this one!

  • http://www.stevemullencreative.com Steve Mullen

    Good points in this article. One thing to point out on the label tag that is often over looked. The label tag is a clickable element that will focus the input, that’s right, go try it for yourself. However for whatever reason it does not default to a pointer cursor. In your css if you add cursor:pointer; to your label element you will help users understand that that can click on the label. Very small thing but every bit of usability helps.

  • Ash

    Great tut, will bookmark this – thanks !

  • Victor

    This was extremely useful as I am just starting to pay more attention to usability and accessibility. Thank you very much for this article.

  • Steve

    Great info! I am really enjoying these beginners articles. I have been working in ASP .Net on and off for a couple of years for internal apps. Now I am seeing how much has been hidden from me through VS. It is a great “get it done” tool but I realize that I know nothing about HTML so this is good stuff.

  • http://www.highlydriven.com Aaron

    Nice post, thank you very much for sharing.
    The label for= is a new one to me and I just had to go back to my most recent forms and make sure I added those, very cool!

  • http://acrisdesign.com Vikas

    Great info. Thx you

  • Peace4man

    Great job! thanks !

  • http://myfacefriends.com Myfacefriends

    lovely tuts! thanks!

  • http://abdusfauzi.com xun

    nice post. really good for beginners so start messing up with form for cross browser :)

  • http://www.shockwork.net Robert

    You always, and I repeat ALWAYS do use where you need your user to interact. And why? Because of screen readers, you miss out on accesibility by using or . The screen reader wont be able to see for which field the span belongs too. Just to point it out.

    DO NOT USE FOR FIELDS, READ THE ABOVE :)