Forms, jQuery and CSS3

Everyone needs to create a form at one point or another and I’ve got a few rules I generally stick to when designing and developing forms in general.

Forms jQuery and CSS3
Before we get started on actually coding the form, let’s recap on the dos and don’ts of forms

It should be simple

It can get complicated quite quickly

This could confuse you and/or the user. If the user gets confused, lost or overwhelmed, there is a high chance that he/she will close the page and you will have lost a potential customer/submitter.

Avoid overwhelming the user

Don’t give the user unnecessary options, such as “Fill this in if you have chose option B”. Rather have an extra field fade in or pop-up if a certain option was chosen. Create a mini wizard if it is appropriate.

Validation syndrome

Don’t add captchas, validate the names, surnames, telephone numbers and emails unless you are getting spammed with false information all the time. Validation is there to help the user as well as obtain valid information, so don’t give the users a bad user experience.

Be wise, Optimize

The content should be efficient.

Don’t ask for unnecessary information. The longer it takes for the person to complete the form, the higher the chance is that he/she may leave.

The HTML should be as simple as possible. – Semantic markup makes your browser smile

don’t use <div>s when you don’t need to. I’ve found pre-defined elements work better cross-browser than divs. We have <form>, <fieldset>, <legend>, <label>, <input>, <select> and <option> to work with. They were created for a reason, use them.

Visually appealing

Don’t over do the CSS3

Sometimes people inappropriately overdo the drop/text-shadow and it gives me the impression that the site was designed by an amateur developer.

Be subtle

You could use drop shadows, text-shadows, rounded corners, hover and focus events, etc. every single time you develop anything, but be subtle. A drop-shadow or text-shadow that is barely noticible at first could make a whole world of difference to the atmosphere of the web-page.

Now that we have the basics down, let’s get started.

The plan

My plan is to create a wizard-type form – with next and previous buttons – in order to add an element of simplicity. Basically, I’m going to follow the above ‘tips’ and use them while I create this form.

The HTML

<form action="">
    <fieldset>
        <legend>Step One</legend>

        <label for="name">Name:</label>
	<input id="name" name="name" type="text" size="20" />
        
        <label for="email">Email:</label>
	<input id="email" name="email" type="text" size="25" />
    </fieldset>
    
    <fieldset>
        <legend>Step Two</legend>

        <label for="company">Company:</label>
	<input id="company" name="company" type="text" size="20" />
        
        <label for="tel-no">Tel No:</label>
	<input id="tel-no" name="tel-no" type="text" size="20" />
        
        <label for="fax-no">Fax No:</label>
	<input id="fax-no" name="fax-no" type="text" size="20" />
    </fieldset>
    
    <fieldset>
        <legend>Step Three</legend>

        <label for="country">Country:</label>
	<input id="country" name="country" type="text" size="20" />
        
        <label for="address">Address:</label>
	<input id="address" name="address" type="text" size="20" />
        
        <label for="state">State:</label>
        <select id="state" name="state">
        <option value="Option one">Option one</option>
        <option value="Option two">Option two</option>
        <option value="Option three">Option three</option>
        </select>
        
        <br class="clear" />
        
        <input id="submit" type="submit" value="Submit"/>
    </fieldset>
</form>

The HTML is fairly simple. I’ve added the for, name and id attributes because it’s more semantic to do so than to leave it out.

The form has the empty attribute ‘action’ because every form has to have an action. If the action attribute is not added, the page will not validate.

A legend is the heading text on top of the border. It requires no styling (from us) in order to achieve this effect cross-browser. All that is needed is a <legend> within a <fieldset>. Pretty decent, right?

The CSS

form {
	width: 760px;
}
fieldset {
	background: #827254;
	border:2px solid #c7b795;
	margin: 0 0 20px 0;
	padding: 15px 10px;
}
fieldset.submit {
	background: none;
	border: none;
	margin: 0;
	padding: 0 10px;
}
fieldset legend {
	color: #fff;
	font-weight:bold;
	text-shadow: 4px 4px 7px #4d412a;
}
fieldset input {
	border: 1px solid #516764;
	border-right-color: #504532;
	border-bottom-color: #504532;
	height: 25px;
	line-height: 25px;
	margin:0 20px 0 0;
	padding: 0 2px;
}
fieldset input:last-child {
	margin:0;
}
fieldset input:focus {
	border: 1px solid #4d412a;
}
fieldset label {
	margin:0 10px 0 0;
}
fieldset input[type="submit"] {
	background:#827254;
	border:3px solid #585246;
	color:#E5D8B9;
	cursor: pointer;
	height: auto;
	line-height: 15px;
	margin: 20px 0 0 0;
	padding:4px 6px;
}
fieldset input[type="submit"]:hover {
	color: #fff;
}

/*
	Navigation
*/
div.nav {
	width: 200px;
	margin: 0 auto;
}
#prev, #next {
	display: block;
	background:#827254;
	border:3px solid #585246;
	color:#E5D8B9;
	cursor: pointer;
	height: auto;
	line-height: 15px;
	margin: 20px 0 0 0;
	padding:4px 6px;
	text-align: center;
	width: 65px;
}
#prev {
	float: left;
}
#next {
	float: right;
}
#prev:hover, #next:hover {
	color: #fff;
}

/*
	CSS3 
*/
fieldset, fieldset input, #prev, #next {
	border-radius: 5px;
	-moz-border-radius: 5px;
}
fieldset {
	box-shadow: inset 0 0 10px #4d412a;
	-moz-box-shadow: inset 0 0 10px #4d412a;
	-webkit-box-shadow: inset 0 0 10px #4d412a;
}
fieldset input:focus {
	box-shadow: inset 0 0 7px #a4a4a4;
	-moz-box-shadow: inset 0 0 7px #a4a4a4;
	-webkit-box-shadow: inset 0 0 7px #a4a4a4;
}
fieldset input[type="submit"]:hover, #prev:hover, #next:hover {
	-moz-box-shadow:0 0 5px #5f553e;
}

In general, I don’t usually use black as a drop-shadow colour. I normally find a darker tone of the background colour and use that.

As you can see, along with CSS3, I’ve used the selector[type="submit"] selector. IE 6 and 7 have a few problems with this (Don’t they always), but I’ve made sure it gracefully degrades.

And here is the IE specific stylesheet:

form{width: 780px;}
fieldset{background: none; }

The jQuery Javascript

I tend to create the javascript after I have completed the HTML and CSS. That way I know that the page will be functional without javascript.

The first thing I’m going to do is remove div#nav from the HTML and inject that into the page via javascript, as it will be a useless element to include if javascript is disabled.

$(document).ready(function(){ 
	
   $("form").prepend('<div class="nav"><a id="prev" href="#">Previous</a><a id="next" href="#">Next</a></div><div class="clear"></div>');
   $("#prev").css("display", "none");
	
  $("fieldset").not(":first").css("display", "none");
	
   $("#next").click(function(){
      $("fieldset:visible").css("display", "none").next().fadeIn();		
      $("#prev").css("display", "block");
		
      if($("fieldset:last").is(":visible")){
         $("#next").css("display", "none");
      }
   });
	
   $("#prev").click(function(){
      $("fieldset:visible").css("display", "none").prev().fadeIn();	
      $("#next").css("display", "block");
		
      if($("fieldset:first").is(":visible")){
         $("#prev").css("display", "none");
      }
   });
	
});

The jQuery is saying:

  1. Target the form and prepend the HTML we typed up earlier
  2. Target #prev and hide it – So that the users can’t click previous while they are on slide one
  3. Target fieldset, but not the first fieldset, and change the display to none
  4. When you click on next, hide the visible fieldset, and display the next fieldset
  5. Whenever next is clicked, the display of #prev is changed to block – Because there is never a scenario where #prev should be hidden once next is clicked
  6. When you click on next, hide the visible fieldset, and display the next fieldset
  7. If the last fieldset is visible, hide the #next button in order stop the user from continuing past the last slide
  8. And finally, if #prev is clicked, do the exact opposite of #next

Pretty cool how jQuery reads so nicely, huh?
$("fieldset").not(":first").css("display", "none"); – Target fieldset, not the first, change the CSS display property to none.

If you have any questions or anything to say, feel free to leave a comment.

Any questions or comments?

  1. Stefan says:

    Nice article. Regarding validation; one should validate all the inputs from a user/visitor when the information needs to be stored in a database, as a simple SQL injection attack can create havoc.

    As the saying goes, trust no one, especially your users/visitors.

    Keep up the good work.

  2. Stefan says:

    On more thing regarding validation, don’t rely too much on javascript validation, as someone can just disable it and submit the form million of times. Make sure there is always a backup plan for validation when javascript is fails.

    1. Jamy Golden says:

      Yeah, good point. Validation is definitely important. I’m planning on writing an article covering validation sometime soon.

      I think people should be sure that the level of validation they plan on implementing is appropriate. For example, adding one of those crazy google captchas in order to add a comment on this blog would be silly.

    2. Stefan says:

      That would be silly, as WordPress has Akismet to take care of all the spam. Captcha validations should be used only when absolutely necessary or if ones form keeps getting a lot of spam.

      Good luck with the validation article, will be interesting reading.

  3. Thanks a lot Jamy Golden for sharing this. I was going to do it from scratch and not follow a guide/tutorial but then after spending an hour trying to start windows 7 in safe mode to remove a program I didn’t want I was running short on time. But probably saved 2hrs now so I guess I still an hour up!

    1. Jamy Golden says:

      It’s my pleasure. I’m glad you found it useful :)

  4. BojaX says:

    Great :'(
    im blaming myself why didnt i found this before…