Watch our 3-minute video to find out how you can learn CSS with a live instructor.
Additional Resources

Laying out and Styling Forms with CSS

In this lesson of the CSS tutorial, you will learn...
  1. To use CSS to layout forms.

HTML Forms are often laid out with two-column tables with the label in the left column and the form field in the right. One could argue that there is nothing semantically wrong with this as the labels are really like headers for the values in the form controls. However, that argument falls apart when table cells are joined (with colspan) as the often are to fit wider form controls such as textareas.

Even if you were to carefully layout the form so that the label were in the left column and the form field in the right, the table is at best extraneous. The label tag serves the purpose of providing a "heading" for the form field.

In this lesson of the CSS tutorial, we'll learn how to layout forms without tables using CSS.

Laying out the Questions

Most forms can be thought of as a series of questions:

  1. What is your first name?
  2. What is your last name?
  3. What company do you work for?

But instead of being laid out as questions, they are presented as answer spaces (form controls) preceded by labels:

  1. First Name: __________________________
  2. Last Name: __________________________
  3. Company: __________________________

So, in creating an HTML page, it makes sense to use an ordered list. In fact, let's start with that:

The code for this page is shown below:

Code Sample: CssForms/Demos/JobApplication1.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Job Application</title>
</head>
<body>
<h1>Job Application</h1>
<h2>Job Information</h2>
<ol>
 <li>Job of Interest (Sales Manager, Account Executive, Receptionist, Marketing Director)</li>
 <li>Referral Source (Advertisement, Employee, Employement Agency, Website)</li>
 <li>Availability (Full-Time, Part-Time, Temporary, Seasonal)</li>
 <li>Location (New York, California, Texas, Pennsylvania, Kansas)</li>
</ol>
<h2>Personal Information</h2>
<ol>
 <li>First Name</li>
 <li>Last Name</li>
 <li>Street Address</li>
 <li>City</li>
 <li>State</li>
 <li>Postal code</li>
 <li>Telephone</li>
 <li>Email address</li>
 <li>Citizenship</li>
 <li>Have you ever been convicted of a felony?</li>
 <li>Are you willing to relocate?</li>
</ol>
<h2>Employment History</h2>
<p>Provide your employment history starting with the company for which you have most recently worked.</p>
<ol>
 <li>Company 1
  <ol>
   <li>Company Name</li>
   <li>Job Title</li>
   <li>Start Date</li>
   <li>End Date</li>
   <li>Responsibilities</li>
   <li>Reason for leaving</li>
  </ol>
 </li>
 <li>Company 2
  <ol>
   <li>Company Name</li>
   <li>Job Title</li>
   <li>Start Date</li>
   <li>End Date</li>
   <li>Responsibilities</li>
   <li>Reason for leaving</li>
  </ol>
 </li>
 <li>Company 3
  <ol>
   <li>Company Name</li>
   <li>Job Title</li>
   <li>Start Date</li>
   <li>End Date</li>
   <li>Responsibilities</li>
   <li>Reason for leaving</li>
  </ol>
 </li>
</ol>
</body>
</html>
Code Explanation

As you can see, there is no CSS in this file. It's a simple HTML file split into separate sections of pseudo-questions, which are presented in ordered lists.

The pseudo-questions will become our form labels.

Creating the Form

Now we'll begin creating the form. We won't add the form controls just yet. First, we want to capture the structure within a form:

Code Sample: CssForms/Demos/JobApplication2.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Job Application</title>
<style type="text/css">
 /* added to call out fieldsets */
 fieldset {
  border-color:#000;
 }
 fieldset fieldset {
  border-style:dashed;
 }
</style>
</head>
<body>
<h1>Job Application</h1>
<form method="post" action="apply.php">
 <fieldset>
  <legend>Job Information</legend>
  <ol>
   <li>Job of Interest (Sales Manager, Account Executive, Receptionist, Marketing Director)</li>
   <li>Referral Source (Advertisement, Employee, Employement Agency, Website)</li>
   <li>Availability (Full-Time, Part-Time, Temporary, Seasonal)</li>
   <li>Location (New York, California, Texas, Pennsylvania, Kansas)</li>
  </ol>
 </fieldset>
 <fieldset>
  <legend>Personal Information</legend>
  <ol>
   <li>First Name</li>
   <li>Last Name</li>
   <li>Street Address</li>
   <li>City</li>
   <li>State</li>
   <li>Postal code</li>
   <li>Telephone</li>
   <li>Email address</li>
   <li>Citizenship</li>
   <li>Have you ever been convicted of a felony?</li>
   <li>Are you willing to relocate?</li>
  </ol>
 </fieldset>
 <fieldset>
  <legend>Employment History</legend>
  <p>Provide your employment history starting with the company for which you have most recently worked.</p>
  <fieldset>
   <legend>Company 1</legend>
   <ol>
    <li>Company</li>
    <li>Title</li>
    <li>Start Date</li>
    <li>End Date</li>
    <li>Responsibilities</li>
    <li>Reason for leaving</li>
   </ol>
  </fieldset>
  <fieldset>
   <legend>Company 2</legend>
   <ol>
    <li>Company</li>
    <li>Title</li>
    <li>Start Date</li>
    <li>End Date</li>
    <li>Responsibilities</li>
    <li>Reason for leaving</li>
   </ol>
  </fieldset>
  <fieldset>
   <legend>Company 3</legend>
   <ol>
    <li>Company</li>
    <li>Title</li>
    <li>Start Date</li>
    <li>End Date</li>
    <li>Responsibilities</li>
    <li>Reason for leaving</li>
   </ol>
  </fieldset>
 </fieldset>
 <fieldset>
  <input type="reset" id="Reset" name="Reset" value="Start Over" />
  <input type="submit" id="Submit" name="Submit" value="Submit" />
 </fieldset>
</form>
</body>
</html>
Code Explanation

Things to notice:

  • In JobApplication1.html, we had used a nested ordered list to capture the parent-child relationship between "Employment History" and the individual companies for which the applicant has worked. Here in JobApplication2.html, we've replaced that structure with nested fieldsets.
  • We have also replaced all the h2 tags with legend tags.
  • We have added buttons nested in a fieldset.

The result is shown below. Note that we have styled the fieldset borders some to call them out. We'll remove those styles later.

The fieldset tag is used to group like form fields. The legend tag is not required in a fieldset, but it is usually a good idea to include it. It provides a title or heading for the grouped elements.

Now let's add the form fields:

Code Sample: CssForms/Demos/JobApplication3.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Job Application</title>
</head>
<body>
<h1>Job Application</h1>
<form method="post" action="apply.php">
 <fieldset id="jobInfo">
  <legend>Job Information</legend>
  <ol>
   <li>
    <label for="JobOfInterest">Job of Interest:</label>
    <select name="JobOfInterest" id="JobOfInterest">
     <option>Account Executive</option>
     <option>Marketing Director</option>
     <option>Receptionist</option>
     <option>Sales Manager</option>
    </select>
   </li>
   <li>
    <label for="ReferralSource">Referral Source</label>
    <select name="ReferralSource" id="ReferralSource">
     <option>Advertisement</option>
     <option>Employee</option>
     <option>Employement Agency</option>
     <option>Website</option>
    </select>
   </li>
   <li>
    <label for="Availability">Availability</label>
    <select name="Availability" id="Availability">
     <option>Full-Time</option>
     <option>Part-Time</option>
     <option>Seasonal</option>
     <option>Temporary</option>
    </select>
   </li>
   <li>
    <label for="Location">Location</label>
    <select name="Location" id="Location">
     <option>California</option>
     <option>Kansas</option>
     <option>New York</option>
     <option>Texas</option>
     <option>Pennsylvania</option>
    </select>
   </li>
  </ol>
 </fieldset>
 <fieldset id="personalInfo">
  <legend>Personal Information</legend>
  <ol>
   <li>
    <label for="FirstName">First Name:</label>
    <input type="text" size="20" name="FirstName" id="FirstName" title="First Name" />
   </li>
   <li>
    <label for="LastName">Last Name:</label>
    <input type="text" size="20" name="LastName" id="LastName" title="Last Name" />
   </li>
   <li>
    <label for="Address">Street Address:</label>
    <input type="text" size="20" name="Address" id="Address" title="Address" />
   </li>
   <li>
    <label for="City">City:</label>
    <input type="text" size="20" name="City" id="City" title="City" />
   </li>
   <li>
    <label for="State">State:</label>
    <input type="text" size="20" name="State" id="State" title="State" />
   </li>
   <li>
    <label for="PostalCode">Postal Code:</label>
    <input type="text" size="20" name="PostalCode" id="PostalCode" title="Postal Code" />
   </li>
   <li>
    <label for="Telephone">Telephone:</label>
    <input type="text" size="20" name="Telephone" id="Telephone" title="Telephone" />
   </li>
   <li>
    <label for="Email">Email Address:</label>
    <input type="text" size="20" name="Email" id="Email" title="Email Address" />
   </li>
   <li>
    <label for="Citizenship">Citizenship:</label>
    <input type="text" size="20" name="Citizenship" id="Citizenship" title="Citizenship" />
   </li>
   <li>
    <span class="label">Have you ever been convicted of a felony?:</span>
    <label><input type="radio" name="Felony" id="FelonyNo" title="Felony Yes" /> Yes</label>
    <label><input type="radio" name="Felony" id="FelonyYes" title="Felony No" /> No</label>
   </li>
   <li>
    <span class="label">Are you willing to relocate?:</span>
    <label><input type="radio" name="Relocate" id="RelocateNo" title="Relocate Yes" /> Yes</label>
    <label><input type="radio" name="Relocate" id="RelocateYes" title="Relocate No" /> No</label>
   </li>
  </ol>
 </fieldset>
 <fieldset id="employmentHistory">
  <legend>Employment History</legend>
  <p>Provide your employment history starting with the company for which you have most recently worked.</p>
  <fieldset>
   <legend>Company 1</legend>
   <ol>
    <li>
     <label for="CompanyName1">Company Name:</label>
     <input type="text" size="20" name="CompanyName1" id="CompanyName1" title="Company Name" />
    </li>
    <li>
     <label for="JobTitle1">Job Title:</label>
     <input type="text" size="20" name="JobTitle1" id="JobTitle1" title="Job Title" />
    </li>
    <li>
     <label for="StartDate1">Start Date:</label>
     <input type="text" size="20" name="StartDate1" id="StartDate1" title="Start Date" />
    </li>
    <li>
     <label for="EndDate1">End Date:</label>
     <input type="text" size="20" name="EndDate1" id="EndDate1" title="End Date" />
    </li>
    <li>
     <label for="Responsibilities1">Responsibilities:</label>
     <textarea name="Responsibilities1" id="Responsibilities1" title="Responsibilities" cols="50" rows="3"></textarea>
    </li>
    <li>
     <label for="ReasonForLeaving1">Reason for Leaving:</label>
     <textarea name="ReasonForLeaving1" id="ReasonForLeaving1" title="Reason for Leaving" cols="50" rows="3"></textarea>
    </li>
   </ol>
  </fieldset>
---- Code Omitted ----
</fieldset> <fieldset id="buttons"> <input type="reset" id="Reset" name="Reset" value="Start Over" /> <input type="submit" id="Submit" name="Submit" value="Submit" /> </fieldset> </form> </body> </html>

Adding the Form Fields

The page still uses all the default HTML styles. The result is shown below:

Our form is now well structured so that a person viewing it in a browser or using an accessibility device such as a screen reader would be able to follow it easily. A few things to note:

  • We have placed most of the "questions" in label tags and used the for attribute to tie them to their form fields.
  • We have wrapped the radio buttons with their labels in label tags and put the associated questions in span tags, which we have given a "label" class so that we can style them later.
  • We have used the title attribute on all the form fields and assigned it a descriptive value. This is for accessibility purposes. Though most accessibility devices will use the label tag to provide information about the form control, some rely on the control's title attribute.
  • We have added id attributes to the main fieldsets as hooks for our style sheet.

It's almost time to get stylish. We won't need any new CSS properties to style our form. We'll just see how we can use styles we're already familiar with. However, before we do that, we need to go on a little tangent.

Reset Revisited

In the Page Layout lesson, we introduced the following simple CSS reset:

* {
 margin:0;
 padding:0;
 border:0;
}

As we noted there, this effectively does away with all margin, padding and borders for every element. This includes form controls. However, resetting form control styles has some undesirable effects. Eric Meyer covers this in detail in his article at http://meyerweb.com/eric/thoughts/2007/05/15/formal-weirdness. The big takeaway is that different browsers have different default displays for form controls and that it is not possible to reconstruct those displays using CSS, so it's generally better to leave form controls alone.

Meyer provides a more detailed reset at http://meyerweb.com/eric/tools/css/reset/index.html that avoids resetting form controls. You'll find a copy of this file (reset-meyer.css in your CssForms directory. And we will use it in our code here.

Styling the Form

We've just said that we don't want to use CSS to style any of the form controls. But we do want to use CSS to layout the form and we can apply some formatting styles to the form, fieldset and legend elements.

First let's see what happens when we apply Eric Meyer's reset to CssForms/Demos/JobApplication4.html:

Not pretty, but it gives us a fresh start. Let's see what we need to do to the style sheet to make CssForms/Demos/JobApplication5.html look like this:

Let's start by looking at the complete style sheet and then we'll dissect it:

Code Sample: CssForms/Demos/style.css

body {
 background-color:#ccc; 
}

h1 {
 width:555px;
 margin:5px auto;
 padding-bottom:10px;
 border-bottom:1px solid #930;
 font-size:xx-large;
 color:#930;
}

/*Begin Form Styles*/
form {
 width:555px;
 margin:auto;
 padding-bottom:20px;
 color:#930;
}

fieldset {
 margin-bottom:10px;
 border-bottom:1px solid #930;
 background-color:#eec;
}

legend {
 padding-left:10px;
 font-size:1.2em;
 font-weight:bold;
 letter-spacing:.5em;
 font-family:"Trebuchet MS", Arial, Helvetica, sans-serif;
 font-variant:small-caps;
 color:#460;
}

fieldset fieldset {
 margin-top:10px; 
 border-bottom:none;
}

fieldset fieldset legend {
 font-size:1em;
 font-weight:bold;
 letter-spacing:.4em;
 font-family:"Trebuchet MS", Arial, Helvetica, sans-serif;
 color:#333;
}

form ol {
 padding:20px;
}

fieldset fieldset ol {
 margin-top:-10px;
}

form p {
 margin:10px;
 font-size:.8em;
}

form li {
 list-style-type:none;
 border-bottom:1px dotted #000; 
 padding-bottom:2px;
 margin-bottom:2px;
}

label {
 display:block;
 width:200px;
 float:left;
 font-weight:bold;
}

span.label {
 font-weight:bold;
}

li.radioContainer label {
 float:none;
 font-weight:normal;
}

select, input[type="text"] {
 width:200px; 
}

textarea {
 width:400px;
 height:50px;
}

#buttons {
 text-align:center; 
}

#buttons input {
 height:50px;
 width:150px;
 font-size:1.5em;
 color:#930;
 font-variant:small-caps;
 margin:10px;
}
/*End Form Styles*/

Most of the CSS should be pretty easy to follow. Here are some things to notice:

  1. The rule below takes away the bottom border from fieldsets that are nested within other fieldsets:
    fieldset fieldset {
     margin-top:10px; 
     border-bottom:none;
    }
  2. The selector fieldset fieldset legend only applies to legends inside of fieldsets that are nested within other fieldsets. This is to make the "headings" of form subsections appear differently from the headings of the main sections.
  3. The rule below removes the numbers from the list items, adds a dotted line beneath each "question", and creates some vertical space between the "questions."
    form li {
     list-style-type:none;
     border-bottom:1px dotted #000; 
     padding-bottom:2px;
     margin-bottom:2px;
    }
  4. The rule below changes the label from an inline element (default) to a block-level element. This makes it possible to apply the float:left; declaration, which will bring its associated form control up to the right of the label.
    label {
     display:block;
     width:200px;
     float:left;
     font-weight:bold;
    }
  5. This rule turns off the float property for labels that appear in list items with the "radioContainer" class:
    li.radioContainer label {
     float:none;
     font-weight:normal;
    }
    Remember, these are the label elements that surround the radio button and its presentation value, like this:
    <li class="radioContainer">
     <span class="label">Have you ever been convicted of a felony?:</span>
     <label><input type="radio" name="Felony" id="FelonyNo" title="Felony Yes" /> Yes</label>
     <label><input type="radio" name="Felony" id="FelonyYes" title="Felony No" /> No</label>
    </li>
  6. This rule sets a width for the select and text input elements:
    select, input[type="text"] {
     width:200px; 
    }
  7. This rule sets a height and width for the textareas, overriding the cols and rows values:
    textarea {
     width:400px;
     height:50px;
    }
  8. And these last two rules style the buttons:
    #buttons {
     text-align:center; 
    }
    
    #buttons input {
     height:50px;
     width:150px;
     font-size:1.5em;
     color:#930;
     font-variant:small-caps;
     margin:10px;
    }
    Note that we recommended earlier that you should leave form controls alone. Changing the height and width of form controls doesn't change any of their other default behaviors or styles, so this is not necessarily bad, but you should certainly test it carefully in all your target browsers and operating systems.

Although there are other ways to layout the HTML for forms, we like the use of an ordered list (see footnote) as it makes sense semantically and doesn't require extraneous tags used for formatting purposes only.

Exercise: Expanding the Form

Duration: 10 to 25 minutes.

In this exercise, you will add an "Education" section to the form.

  1. Open CssForms/Exercises/JobApplication.html in your editor.
  2. Expand the form to cover the following:
    1. Education
      1. Degree 1
        1. Institution
        2. Type of Degree
        3. Year Completed
        4. Comments
      2. Degree 2
        1. Institution
        2. Type of Degree
        3. Year Completed
        4. Comments

Try to layout the form in two columns like this:

Note that there are several ways to do this; however, it is very difficult to get this layout to look the same across browsers without using some hacks. See if you can do it in one browser. Our solution uses relative positioning and the screenshot is from Firefox. It would look almost the same in other modern browsers. (see footnote)

Laying out and Styling Forms with CSS Conclusion

In this lesson of the CSS tutorial, you have learned to use CSS to layout and style forms. Although there is nothing wrong with trying to make nice looking forms, you should be sure that you don't surprise your users too much. Most people have filled out hundreds of web forms and their expectations are well ingrained. You want to be sure that your forms aren't so stunning that the user is left not knowing what to do.

Footnotes

  1. The idea of laying out forms as ordered lists originally came from Nick Rigby's "Prettier Accessible Forms" at http://www.alistapart.com/articles/prettyaccessibleforms.

  2. A solution that corrects the differences in Internet Explorer is shown in CssForms/Solutions/JobApplication-challenge-IE.html, but this contains content not yet covered in this course.

To continue to learn CSS go to the top of this page and click on the next lesson in this CSS Tutorial's Table of Contents.
Last updated on 2009-10-16

Use of http://www.learn-css-tutorial.com (Website) implies agreement to the following:

Copyright Information

All pages and graphics on Website are the property of Webucator, Inc. unless otherwise specified.

None of the content on Website may be redistributed or reproduced in any way, shape, or form without written permission from Webucator, Inc.

No Printing or saving of pages or content on Website

This content may not be printed or saved. It is for online use only.


Linking to Website

You may link to any of the pages on Website; however, you may not include the content in a frame or iframe without written permission from Webucator, Inc.


Warranties

Website is provided without warranty of any kind. There are no guarantees that use of the site will not be subject to interruptions. All direct or indirect risk related to use of the site is borne entirely by the user. All code and explanations provided on this site are provided without warranties to correctness, performance, fitness, merchantability, and/or any other warranty (whether expressed or implied).


For individual private use only

You agree not to use this online manual to deliver or receive training. If you are delivering or attending a class that is making use of this online manual, you are in violation of our terms of service. Please report any abuse to courseware@webucator.com. If you would like to deliver or receive training using this manual, please fill out the form at http://www.webucator.com/Contact.cfm