Style Web Forms Using CSS

A big part of our work as website designers is the ability to make things look good and function well. We spend hours taking the time to make every aspect of our site visually compelling, intuitive, user friendly, accessible and overall beautiful. Our forms are no exception! Our forms should be beautiful, easy to use, and should look consistent with the rest of our website. We can do this easily with CSS.

The process isn’t difficult, you just can to know what each tag does, and how to style it. The first thing we need to do is bring in our HTML. Below is the HTML found in our sample form.

<form>
<div>
<h1>Contact Form :</h1>
<label>
<span>Your name</span><input id="name" type="text" name="name" />
</label>

<label>
<span>Email Address</span><input id="email" type="text" name="email" />
</label>

<label>
<span>Subject</span><input id="subject" type="text" name="subject" />
</label>

<label>
<span>Message</span><textarea id="feedback" name="feedback"></textarea>
<input type="button" value="Submit Form" />
</label>

</div>
</form>

You will notice that in the HTML, I used words, names, and ids that make sense. They are consistent with what you’d expect each field to be called. Each Field is wrapped in a label tag to make things easy for us to style. Our form looks pretty plain without any styling, as you can see from the sample below:

Our form has no structure, no color, and no personality. We can change that with a little bit of code. First, we are going to style the form tag itself.


form    {
background: -webkit-gradient(linear, bottom, left 175px, from(#CCCCCC), to(#EEEEEE));
background: -moz-linear-gradient(bottom, #CCCCCC, #EEEEEE 175px);
margin:auto;
position:relative;
width:550px;
height:450px;
font-family: Tahoma, Geneva, sans-serif;
font-size: 14px;
font-style: italic;
line-height: 24px;
font-weight: bold;
color: #09C;
text-decoration: none;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
padding:10px;
border: 1px solid #999;
border: inset 1px solid #333;
-webkit-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
-moz-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
}

The code above can look like a mouthful, but it is fairly simple when broken down. Flat colors can be really boring, so adding a slight gradient can break up the monotony and give your design some dimension. That is done with the background style. When using this property and gradients, you have to include the specific prefixes for certain browsers such as FireFox, or they won’t show up. Both are saying the same thing. Create a linear gradient, start from the bottom, and use a medium gray and a light gray and blend it over 175px.

Since this is where you entire form is going to be contained, I decided to center the form in the browser by setting margin to auto. Setting the Position to Relative is intended for aligning an element later, so that explanation is to come. I specified the width and the height of the form, the fonts used, and styled it to be bold, italic,  14px in size and a line height (spacing between each line of text) of 24px.

Border radius gives us rounded corners for our boxes, but just like with gradients, you have to specify the prefix for each browser. Increase the number for more rounded corners. Padding gives some space between the text and the edge of the form, so that your text doesn’t run outside the bounds of your form and its rounded corners.

You can create subtle borders for contrast and dimension. I also added box shadows to the overall form, so if this becomes a popup form, it will add dimension and make the form look like it is floating over the rest of the site. This is a popular technique right now. This is yet another style that needs you to specify the proper prefix in order to get it to show up. You form should look something like this:

Next, we should style the input area. That is where the text is actually entered into each field.

input    {
width:375px;
display:block;
border: 1px solid #999;
height: 25px;
-webkit-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
-moz-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
}

The code shown above selects all of the text input areas, and styles them to be 375px wide, and setting the display to block stacks them vertically. Adding a 1px border helps to emphasize each input area, and setting the height to 25px gives the user plenty of room visually to enter their text.

I added a box shadow for dimension, but remember to include the prefix for each browser. The first 2 digits control the offset for the shadow. Positive numbers push the shadow to the right  and up, and negative numbers push it to the left and down. The 3rd number determines how much the shadow is blurred. The higher the number, the larger the blur. Inside of the parenthesis, the 1st three numbers determine the red, green, and blue values of the shadow, and the decimal number determines the opacity of the shadow itself. 1 is 100% opacity and 0.1 is 10% opacity. With these style added, your form should begin to take shape, and look like the image below:

Everything is aligned, but notice that the submit button has been affected b the width styling. We will fix this later. The message area doesn’t look right, but we can fix this easily.

textarea#feedback {
width:375px;
height:150px;
}

You can specify the width and the height directly, but this still doesn’t make the text area fall in line with the other fields.

We have to set the display Property to Block manually, so that is performs the same way as the input areas.

textarea.message {
display:block;
}

Now that everything is aligned properly, we can get down to fixing the submit button. The CSS that we need to fix this is fairly simple:

input.button {
width:100px;
position:absolute;
right:20px;
bottom:20px;
background:#09C;
color:#fff;
font-family: Tahoma, Geneva, sans-serif;
height:30px;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
border: 1p solid #999;
}
input.button:hover {
background:#fff;
color:#09C;
}

We select the button named submit and  define its width to 100px and set its position to absolute. As we mentioned earlier, we had styled the form to have a relative position. The way this works is that when you set something to have a absolute position, it looks for the last element that has its position set to relative. If that element is nested inside of the element with a position of relative, its absolute position is relative to that element. In other words, the submit button will be positioned somewhere inside of the bounds of the form container. I defined that it will be 20px from the right and from the bottom with those respective styles.

I set the background to blue and the text to white. I gave it a definite height of 30px and rounded corners. I also have it a 1px gray border. This is the normal state for your submit button.

You will notice that I defined a hover state for the submit button. The styles defined here override the original styling once the user hovers over the button. I changed the background to white and the text to blue, giving the user a highly contrasting effect when they mouse over the button.

Here is the normal state:

Here is the hover state:

Our form’s structure is done. You could stop here and you would have a great form, all styled with CSS. However, you could take it one step further, by adding a little user friendly styling to the text input areas, so that the user can tell where they are typing. You can do this with a small amount of CSS:

textarea:focus, input:focus {
border: 1px solid #09C;
}

What this does is it tells the browser that if a person has a text input or text area selected, that it needs to add a 1px blue border around the active input area, so the user knows where they are visually in the form. This is just a little extra something that is much appreciated by many users.

Conclusion

You can do some wonderful things with CSS, including creating beautiful web forms for your users. With just a little CSS and some imagination, you can make something as boring as filling out a form, much more enjoyable for anyone who is visiting your site.

If you enjoyed reading this post, you’ll love Learnable; the place to learn fresh skills and techniques from the masters. Members get instant access to all of SitePoint’s ebooks and interactive online courses, like Styling Forms with CSS.

Style your own forms from the ground up with HTML5 and CSS3 – our new CSS forms course is here, and it’s free with a Learnable trial!

Comments on this article are closed. Have a question about CSS? Why not ask it on our forums?

Win an Annual Membership to Learnable,

SitePoint's Learning Platform

  • Chris Allen Aaker

    How do I get permanent text (i.e. a label with in the text field) to display on my text fields. Kind of like twitter but ones that do not disappear with the onclick

    • http://pulse.yahoo.com/_L5AVXSH7OFHI5YSAJYCO2GGCDU Savannah Hogan

      I just paid $22.87 for an iPad2-64GB and my girlfriend loves her Panasonic Lumix GF 1 Camera that we got for $38.76 there arriving tomorrow by UPS. I will never pay such expensive retail prices in stores again. Especially when I also sold a 40 inch LED TV to my boss for $675 which only cost me $62.81 to buy. Here is the website we use to get it all from, CoolCent. com

    • http://baldguywebdesign.com Pete

      Chris,

      In order to achieve that desired effect you would simply add onfocus=”value=””
      to the end of your input string.
      eg:

      Hope that helps!

    • Anonymous

      just put value inside the tag …value=”Your text”….

    • McBenny

      Hello Chris,

      The best way to achieve this is to use the new HTML5 form input attribute: “placeholder”. For the supporting browser, it gives the full fonctionnality you’re thinking of and you don’t have to code any line of javascript. If a browser doesn’t support it, it will have no effect.

      Hope this helps

  • http://www.nmcmahon.co.uk Niall McMahon

    Shouldn’t have -ms- and -o- vendor prefixes been used? This is the exact reason why Opera are implementing -webkit- prefixes.

  • Dave Porter

    I think the css starting input.button is incorrect ?
    I could not get the button to style, so I added class=”button” and it now works !

    HTH, Dave

  • http://www.devseo.co.uk/ Alex Hall

    Or, use Twitter’s Bootstrap :-)

  • Chris

    James, while the idea for this post was good, the implementation was terrible. That form looks absolutely horrendous.

    • Al

      Stop hating.. form looks good enough and this wasn’t a design lesson.. it was a quick, concise effective demo in styling a form without too much B.S added.
      Great article!

  • http://blogthingsdot.blogspot.com dan the blogger

    Thank you – every web designer and developer needs to have their own library and template of good styles just like this.

    a ‘raw design’ just isn’t suitable these days on web sites.

  • John

    This does not seem very semantic to me:

    Your name

    The input field is not part of the label, so I don’t believe it should be contained within the tag.

    • Patrick

      Exactly. Semantic code would make use of the “for” attribute of the label tag, and there wouldn’t be a span tag in the label either. I’m also not sure why the entire form is wrapped in an unnecessary div which is not styled at all in the CSS. Forms are block level elements by themselves. You could easily reduce the amount of code here while still achieving the same end result, and actually making the HTML more semantic in the process.

      This article isn’t bad, but it’s sad to see basic errors like this creep into a tutorial article aimed at beginners.

  • http://www.deathshadow.com deathshadow

    Given that it’s a single line of inaccessible trash when there’s no CSS, the lack of BR in it pretty much means it doesn’t matter how pretty you make it with CSS. Like another poster I dislike wrapping the input inside the label, and if you were making the inputs display:block you wouldn’t need the spans anyways.

    Which is why I’d wrap the labels with LABEL not span, leave the input as kin, and use BR so you actually have a useful form for the people who are browsing without CSS aren’t left out in the cold; graceful degradation you know.

    That said, It was VERY pleasing to see someone NOT waste time with idiotic garbage like abusing a definition list or table for no good reason.

  • Richard Mossman

    Since this is a “beginner’s” article, I guess I can ask a “beginner’s” question.

    How do I change things (say replace the Name field with two fields for “first name” and “last name” and have them appear on the same line? But, I still want the other fields to appear on separate lines.

    Thanks

  • Melnykov Alex

    And you should add string ‘margin-bottom: 10px;’ to the ‘input’ selector to get result as shown.

  • http://smartnettechnologies.com Tonatiu Camarillo

    For mi no work fine I fix width this:
    form {
    background: -webkit-gradient(linear, bottom, left 175px, from(#CCCCCC), to(#EEEEEE));
    background: -moz-linear-gradient(bottom, #CCCCCC, #EEEEEE 175px);
    margin:auto;
    position:relative;
    width:550px;
    height:350px;
    font-family: Tahoma, Geneva, sans-serif;
    font-size: 14px;
    font-style: italic;
    line-height: 24px;
    font-weight: bold;
    color: #09C;
    text-decoration: none;
    -webkit-border-radius: 10px;
    -moz-border-radius: 10px;
    border-radius: 10px;
    padding:10px;
    border: 1px solid #999;
    border: inset 1px solid #333;
    -webkit-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
    -moz-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
    box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
    }

    input {
    width:375px;
    display:block;
    border: 1px solid #999;
    height: 25px;
    -webkit-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
    -moz-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
    box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
    }

    textarea {
    width:375px;
    height:100px;
    display:block;
    border: 1px solid #999;
    -webkit-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
    -moz-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
    box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.3);
    }

    textarea.message {
    display:block;
    }
    button#enviar {
    width:100px;
    position:absolute;
    right:20px;
    bottom:20px;
    background:#09C;
    color:#fff;
    font-family: Tahoma, Geneva, sans-serif;
    height:30px;
    -webkit-border-radius: 15px;
    -moz-border-radius: 15px;
    border-radius: 15px;
    border: 1p solid #999;
    }
    button#enviar:hover {
    background:#fff;
    color:#09C;
    }
    textarea:focus, input:focus {
    border: 1px solid #09C;
    background-color: #ccffff;
    }

  • Bharadwaj

    don’t you think this line in HTML file should be

    this one instead:

    the submit button CSS isn’t working the other way…

  • http://www.meta-blogger.com Michael Hall

    Nice tutorial, i like the final look, but unfortunately i’d never use it as-is because the first thing that should be done is to make sure the form looks good in plain old html for browsers that don’t support css or have it turned off before making it look good with with css. and finally javascript if needed.

  • La perle

    Now, I’m winning for the best beginner’s question. Where do I paste that code? In the Head section of the Body section?. Thank you.

  • http://crowdogs.com Peter Schreiner

    How does a comment like this get past the censors?