Adding style with CSS: a beautiful form

31 January 2009, in CSS, HTML | 17 comments »

Forms don’t have to be ugly and boring, and certainly don’t have to be inside tables to look nice and aligned.
In this post we’ll take look at how to style a beautiful form using the power of semantic HTML and CSS.

The beginning: HTML markup

Let’s begin by creating a simple feedback form. Here’s an example of the markup for one:

<form action="form.php">

	<p>Send us your comments and feedback:</p>



        		<label for="name">Name</label>
        		<input type="text" name="name" id="name" />

        		<label for="email">Email</label>

        		<input type="text" name="email" id="email" />

        		<label for="website">Website</label>
        		<input type="text" name="website" id="website" />


        		<label for="message">Message</label>
        		<textarea name="message" id="message"></textarea>

        		<button type="submit" id="send">Send</button>



Breaking down the markup

I used an ordered list to wrap the form elements so each list item is a pair for label + input/textarea. This will not only make it a bit easier to add the style to the form, but will also make the form look better and visually make more sense when no styles are applied to it.

Every element in the form has its own label (except those that have their value specified within the element itself, like buttons and submit inputs).

You might have previously seen forms on other websites that allow you to select the labels, resulting in the right input will becoming highlighted. This removes the necessity of having to point precisely to the input fields – isn’t it more user friendly?

The way to achieve this is by defining which label belongs to which input (or textareas, selects, etc.), and you do that with the for attribute (in the labels) in conjunction with the id attributes in the inputs.

When creating the form, I didn’t use the fieldset or legend tags because our form is simple and short, so there’s really no point to separating it into more than one fieldset, and the paragraph explains what the form is about without being repeated by the screen-readers with each and every label (like legends are).

It’s also worth noting that in this example I chose the button tag, instead of the input tag, for the submit button. This decision was made to give you more options in terms of what you can visually do with it.

Adding the style

Moving onto the CSS part of the form, we’ll start by resetting the default styles, adding some style to our form tag – font, background, margins and padding. We’ll also add a bottom margin to our paragraph.

body {

p {
	margin:0 0 10px 0;

form {
	font:13px Georgia, "Times New Roman", Times, serif;
	padding:10px 20px;

Now, let’s style the ordered list and then make some tweaks for the one that holds the submit button (to which we gave a specific id of “send”).

	form ol {

		form li {

			form li#send {

Our form is taking shape now, but we still need to style the labels, the inputs and the textarea. We should also add a different style for when our inputs are in focus.

		form label {
			line-height:23px;	 /* This will make the labels vertically centered with the inputs */

		form input,
		form textarea {
			font:13px Georgia, "Times New Roman", Times, serif;
			border:1px solid #999999;

			form input:focus,
			form textarea:focus {
				border:1px solid #666;

Last, but certainly not least, let’s add some eye candy to the Send button:

		form li#send button {
			background:#003366 url(images/css-form-send.gif) no-repeat 8px 50%;
			padding:4px 8px 4px 28px;
			border-radius:15%; /* Don't expect this to work on IE6 or 7 */
			margin-left:77px; /* Total width of the labels + their right margin */

			form li#send button:hover {

So what have we added in this last step? We changed the default border (border), background colour (background) and text colour (color) of the button to our own needs. We also added some padding to give the text some space to breath and extra left padding to add a little icon on the background.

The properties border-radius, -moz-border-radius and -webkit-border-radius are CSS3 properties that add rounded corners to our element. Because the border-radius property is still not widely implemented among browsers, we also have to use the browser specific properties that will make it work on Firefox (-moz-border-radius) and Safari (-webkit-border-radius). As you may have guessed, none of the available versions of Internet Explorer supports this feature, so it will be an added detail for more compliant browsers.

For the button to be nicely aligned with the other inputs, we have to add the 77 pixels of left margin (which is the sum of the 70 pixels of the labels + 7 pixels for their right margin).

The cursor:pointer bit is not really necessary, but we’ll then make sure that when a user hovers over the button, the cursor will change to the hand. For browsers other than IE6, it will also change its colour to green (thanks to the form li#send button:hover property).


When it comes down to creating forms, there are actually a lot more things that you can do than meets the eye, just by using some simple CSS. My point in this blog post has been to show that there’s no need to use a table to create visually attractive and usable forms. Especially when we can just as easily have a semantically correct and beautiful form with just a few lines of CSS and some extra hooks in your markup.

View example Download source files

P.S.: Don’t forget to give proper credit to famfamfam (if you use it), for the beautiful Send button icon, that is part of the Silk icons set.


Further reading:

  • Sónia Ribeiro


    Thanks for your help.
    I have a question for you about this exercise:
    why did you use a and not a ?

  • Sónia Ribeiro

    Sorry, ol and not ul

  • @Sónia: Thanks for your comment :)

    I suppose the only reason I chose an ordered list instead of an unordered list was to make it a little more organized.

    For example, when someone is viewing the page with the CSS turned off, it’s clearer to see the order in which he or she has to fill in the form.

    But you could just as easily use UL’s or paragraphs, or even nothing. It’s all a matter of personal preference, I guess.

    Hope this helps!

  • This is a great article. I’m going to use it improve all of the forms on my websites.

    There’s just one thing I need to point out. In the markup for the containing the button, you’ve added the id=”send” to the button and not the

  • Thanks for the form. Very nice. Easy to follow too!

  • b_gates

    Excellent tutorial, huge help, but more importantly, perfect for someone like myself who is just starting out.

    • I have noticed one minor thing though, in IE the “send” button is not round…

    • The field color when selected is also non-showing in IE…

    I remember reading the stylesheet and you already pointing these out….

    Great stuff, thanks a bunch :)

    • Yeah, those are normal behaviours for IE, don’t sweat it! ;)

  • Hello

    A great form I am really impressed.
    I am constructing a website and require a contact form.
    My host uses cgiemai. Do you know if this is a problem converting this code.

    kind Regards
    Maurice Westo

  • Vernon

    There’s a small discrepancy between the HTML and CSS resulting in the send button styling not working. As you can see in the HTML, the id=”send” is an id of the button, not list. Therefore, the two selector lines in the CSS should probably be:

    form li button#send


    form li button#send:hover

    I note that in the download, an alternative solution is to change the id of the list item, and remove the id of the button.

  • Thomas

    Great tutorial. For us newbies who are still feeling our way through the dark, what’s the php code to make it run?


  • Shaique

    Very nice tutorial, this is very helpful to me thanks inayaili .

  • Ronny

    Hello… Tahnks for a great tutorial.

    I was wondering how I can make the input fields have different widths.

    I have a captcha field that needs to be scaled down. Allso I wondered how I can make this css NOT effect the send button.


  • ray dona

    tried to incorporate radio buttons and check boxes into your form but can’t get your form to work with them, i’m unable to align them, they go all over the place, have you any suggestions?

  • Ravi

    Great Tutorial and I simply love it.

    I had a problem. In a single page if I have two forms with different dimensions, I noticed that the CSS properties gets attached to both the forms and the page gets distorted. How can I avoid that ?

  • Thank you inayaili, the form style is clear, elegant and fast.
    very useful for me.

  • JIn

    Nice Tutorial, but it should be corrected on list button id. Not working if ID is on the button.


  • Thanks for that list – by examining one of the examples, i found my typing error, so i can go with my own code :-)