Fancy Sliding Form with jQuery

Tutorials June 7, 2010 by Mary Lou 58 Comments


View demoDownload source

Today we are going to create a fancy sliding form that shows some validation feedback to the user after each step. This form saves a lot of space and is easy to access – it basically works like a slide show, just that we have fieldsets of a form instead of images.

So let’s start!

The Markup

The HTML will consist of a wrapper container where we will place a form with fieldsets. Each fieldset will be a step in our sliding form:

<h1>Fancy Sliding Form with jQuery</h1>
<div id="wrapper">
	<div id="steps">
		<form id="formElem" name="formElem" action="" method="post">
			<fieldset class="step">
				<legend>Account</legend>
				<p>
					<label for="username">User name</label>
					<input id="username" name="username" />
				</p>
				<p>
					<label for="email">Email</label>
					<input id="email" name="email" type="email" />
				</p>
				<p>
					<label for="password">Password</label>
					<input id="password" name="password" type="password" />
				</p>
			</fieldset>
			<fieldset>
			...
			</fieldset>
		</form>
	</div>
	<div id="navigation" style="display:none;">
		<ul>
			<li class="selected">
				<a href="#">Account</a>
			</li>
			<li>
				<a href="#">Personal Details</a>
			</li>
			<li>
				<a href="#">Payment</a>
			</li>
			<li>
				<a href="#">Settings</a>
			</li>
			<li>
				<a href="#">Confirm</a>
			</li>
		</ul>
	</div>
</div>

The navigation with all the links to the steps will be an unordered list that is initially hidden. We will show it in our JavaScript function.
Let’s look at the style.

The CSS

The main wrapper and the steps container will have the following style:

#wrapper{
    -moz-box-shadow:0px 0px 3px #aaa;
    -webkit-box-shadow:0px 0px 3px #aaa;
    box-shadow:0px 0px 3px #aaa;
    -moz-border-radius:10px;
    -webkit-border-radius:10px;
    border-radius:10px;
    border:2px solid #fff;
    background-color:#f9f9f9;
    width:600px;
    overflow:hidden;
}
#steps{
    width:600px;
    overflow:hidden;
}
.step{
    float:left;
    width:600px;
}

The class step will be given to each fieldset. Let’s style the navigation:

#navigation{
    height:45px;
    background-color:#e9e9e9;
    border-top:1px solid #fff;
    -moz-border-radius:0px 0px 10px 10px;
    -webkit-border-bottom-left-radius:10px;
    -webkit-border-bottom-right-radius:10px;
    border-bottom-left-radius:10px;
    border-bottom-right-radius:10px;
}
#navigation ul{
    list-style:none;
	float:left;
	margin-left:22px;
}
#navigation ul li{
	float:left;
    border-right:1px solid #ccc;
    border-left:1px solid #ccc;
    position:relative;
	margin:0px 2px;
}

The single link elements will have a neat CSS3 gradient as background:

#navigation ul li a{
    display:block;
    height:45px;
    background-color:#444;
    color:#777;
    outline:none;
    font-weight:bold;
    text-decoration:none;
    line-height:45px;
    padding:0px 20px;
    border-right:1px solid #fff;
    border-left:1px solid #fff;
    background:#f0f0f0;
    background:
        -webkit-gradient(
        linear,
        left bottom,
        left top,
        color-stop(0.09, rgb(240,240,240)),
        color-stop(0.55, rgb(227,227,227)),
        color-stop(0.78, rgb(240,240,240))
        );
    background:
        -moz-linear-gradient(
        center bottom,
        rgb(240,240,240) 9%,
        rgb(227,227,227) 55%,
        rgb(240,240,240) 78%
        )
}
#navigation ul li a:hover,
#navigation ul li.selected a{
    background:#d8d8d8;
    color:#666;
    text-shadow:1px 1px 1px #fff;
}

When a step get’s validated, we will either add a span indicating that everything is fine, or a span that shows that something is wrong in the form step:

span.checked{
    background:transparent url(../images/checked.png) no-repeat top left;
    position:absolute;
    top:0px;
    left:1px;
    width:20px;
    height:20px;
}
span.error{
    background:transparent url(../images/error.png) no-repeat top left;
    position:absolute;
    top:0px;
    left:1px;
    width:20px;
    height:20px;
}

The styles for the form elements look as follows:

#steps form fieldset{
    border:none;
    padding-bottom:20px;
}
#steps form legend{
    text-align:left;
    background-color:#f0f0f0;
    color:#666;
    font-size:24px;
    text-shadow:1px 1px 1px #fff;
    font-weight:bold;
    float:left;
    width:590px;
    padding:5px 0px 5px 10px;
    margin:10px 0px;
    border-bottom:1px solid #fff;
    border-top:1px solid #d9d9d9;
}
#steps form p{
    float:left;
    clear:both;
    margin:5px 0px;
    background-color:#f4f4f4;
    border:1px solid #fff;
    width:400px;
    padding:10px;
    margin-left:100px;
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;
    -moz-box-shadow:0px 0px 3px #aaa;
    -webkit-box-shadow:0px 0px 3px #aaa;
    box-shadow:0px 0px 3px #aaa;
}
#steps form p label{
    width:160px;
    float:left;
    text-align:right;
    margin-right:15px;
    line-height:26px;
    color:#666;
    text-shadow:1px 1px 1px #fff;
    font-weight:bold;
}
#steps form input:not([type=radio]),
#steps form textarea,
#steps form select{
    background: #ffffff;
    border: 1px solid #ddd;
    -moz-border-radius: 3px;
    -webkit-border-radius: 3px;
    border-radius: 3px;
    outline: none;
    padding: 5px;
    width: 200px;
    float:left;
}
#steps form input:focus{
    -moz-box-shadow:0px 0px 3px #aaa;
    -webkit-box-shadow:0px 0px 3px #aaa;
    box-shadow:0px 0px 3px #aaa;
    background-color:#FFFEEF;
}
#steps form p.submit{
    background:none;
    border:none;
    -moz-box-shadow:none;
    -webkit-box-shadow:none;
    box-shadow:none;
}
#steps form button {
	border:none;
	outline:none;
    -moz-border-radius: 10px;
    -webkit-border-radius: 10px;
    border-radius: 10px;
    color: #ffffff;
    display: block;
    cursor:pointer;
    margin: 0px auto;
    clear:both;
    padding: 7px 25px;
    text-shadow: 0 1px 1px #777;
    font-weight:bold;
    font-family:"Century Gothic", Helvetica, sans-serif;
    font-size:22px;
    -moz-box-shadow:0px 0px 3px #aaa;
    -webkit-box-shadow:0px 0px 3px #aaa;
    box-shadow:0px 0px 3px #aaa;
    background:#4797ED;
}
#steps form button:hover {
    background:#d8d8d8;
    color:#666;
    text-shadow:1px 1px 1px #fff;
}

And now, let’s add some JavaScript magic!

The JavaScript

In our function we will first take care of the display of the slider. For that we need to calculate the width of the elements inside. We will also take care of the sliding when we tab through the inputs. When the user hits tab when he is in the last input of a fieldset, we make the next fieldset slide into place and focus on the first field.

The validation of the form is based on all inputs being required fields. If we slide to the next fieldset and did not fill out all the inputs of the previous one, we will mark the missing inputs with a red background and add our little error span to the navigation item. If everything was fine, we will add the span with the check mark so that the user knows, the step was correct. We will not allow the user to submit the form if one of the steps contains errors.

$(function() {
	/*
	number of fieldsets
	*/
	var fieldsetCount = $('#formElem').children().length;

	/*
	current position of fieldset / navigation link
	*/
	var current 	= 1;

	/*
	sum and save the widths of each one of the fieldsets
	set the final sum as the total width of the steps element
	*/
	var stepsWidth	= 0;
    var widths 		= new Array();
	$('#steps .step').each(function(i){
        var $step 		= $(this);
		widths[i]  		= stepsWidth;
        stepsWidth	 	+= $step.width();
    });
	$('#steps').width(stepsWidth);

	/*
	to avoid problems in IE, focus the first input of the form
	*/
	$('#formElem').children(':first').find(':input:first').focus();	

	/*
	show the navigation bar
	*/
	$('#navigation').show();

	/*
	when clicking on a navigation link
	the form slides to the corresponding fieldset
	*/
    $('#navigation a').bind('click',function(e){
		var $this	= $(this);
		var prev	= current;
		$this.closest('ul').find('li').removeClass('selected');
        $this.parent().addClass('selected');
		/*
		we store the position of the link
		in the current variable
		*/
		current = $this.parent().index() + 1;
		/*
		animate / slide to the next or to the corresponding
		fieldset. The order of the links in the navigation
		is the order of the fieldsets.
		Also, after sliding, we trigger the focus on the first
		input element of the new fieldset
		If we clicked on the last link (confirmation), then we validate
		all the fieldsets, otherwise we validate the previous one
		before the form slided
		*/
        $('#steps').stop().animate({
            marginLeft: '-' + widths[current-1] + 'px'
        },500,function(){
			if(current == fieldsetCount)
				validateSteps();
			else
				validateStep(prev);
			$('#formElem').children(':nth-child('+ parseInt(current) +')').find(':input:first').focus();
		});
        e.preventDefault();
    });

	/*
	clicking on the tab (on the last input of each fieldset), makes the form
	slide to the next step
	*/
	$('#formElem > fieldset').each(function(){
		var $fieldset = $(this);
		$fieldset.children(':last').find(':input').keydown(function(e){
			if (e.which == 9){
				$('#navigation li:nth-child(' + (parseInt(current)+1) + ') a').click();
				/* force the blur for validation */
				$(this).blur();
				e.preventDefault();
			}
		});
	});

	/*
	validates errors on all the fieldsets
	records if the form has errors in $('#formElem').data()
	*/
	function validateSteps(){
		var FormErrors = false;
		for(var i = 1; i < fieldsetCount; ++i){
			var error = validateStep(i);
			if(error == -1)
				FormErrors = true;
		}
		$('#formElem').data('errors',FormErrors);
	}

	/*
	validates one fieldset
	and returns -1 if errors found, or 1 if not
	*/
	function validateStep(step){
		if(step == fieldsetCount) return;

		var error = 1;
		var hasError = false;
		$('#formElem').children(':nth-child('+ parseInt(step) +')').find(':input:not(button)').each(function(){
			var $this 		= $(this);
			var valueLength = jQuery.trim($this.val()).length;

			if(valueLength == ''){
				hasError = true;
				$this.css('background-color','#FFEDEF');
			}
			else
				$this.css('background-color','#FFFFFF');
		});
		var $link = $('#navigation li:nth-child(' + parseInt(step) + ') a');
		$link.parent().find('.error,.checked').remove();

		var valclass = 'checked';
		if(hasError){
			error = -1;
			valclass = 'error';
		}
		$('<span class="'+valclass+'"></span>').insertAfter($link);

		return error;
	}

	/*
	if there are errors don't allow the user to submit
	*/
	$('#registerButton').bind('click',function(){
		if($('#formElem').data('errors')){
			alert('Please correct the errors in the Form');
			return false;
		}
	});
});

And that’s it! I hope you liked the sliding form idea!

View demoDownload source

Tagged with: , , , , ,

Discussion58 Join the discussion

  • Lars

    I like the look and feel of this sign-up dialog. keeps it simple to the user. Great inspiration, good tutorial. Thanks!

  • Michael Pehl

    Uh baby, I like it :)
    Thanks for sharing this one :)

  • Mastercafe

    Really good tutorial, i try similar step’s forms and this is the best that i saw.
    Great work

  • Michael

    Thanks for the tute Mary Lou. Very easy to read and to follow along.

    Great commenting/instructions in the coding as well.

  • Mary Lou

    Thank you all for the great feedback! I’m really glad you like it

  • Elving

    WOW!!! Looks amazing! I never though of doing a sliding form before, its so simple but it brings so much functionality. The design is beautiful too. Its the perfect form!

  • Jireck

    I tired to say always : Great, Marvelous Tutos Mary ;-)

  • egeea

    Fix shift+tab to also go backwards.

  • David

    Very useful. will definitely use it!

  • Alex McCabe

    It’s nice, but if you disable JavaScript it completely fails. It shouldn’t be that hard to fix it, but for the tutorial you should show how to make it available to all users.

  • Mary Lou

    @Alex thank you for your feedback! It is indeed very easy to fix: just remove the height property from the #steps and from .step class in the CSS and the fieldsets will be displayed vertically if JS is disabled. Also, the navigation will not be shown. I updated the demo and the ZIP file, thanks again and cheers, ML

  • David

    @Alex You don’t ask Chicken Curry without the Curry, right? I guess jQuery does not work if you disable JavaScript, and the title of this tutorial explicitly says “with jQuery”

  • Alexandre Gemellaro

    Very interesting and functionally … was clean and occupying very little space!
    Congratulations!

  • ivanking

    really good amongst all the login form

  • Chris Creed

    Thanks Mary – another useful tutorial – very clean and simple :-) I think it breaks up the form filling process nicely which users will appreciate. Much better than having to fill in a larger form on a single page.

  • Laira

    Such a fabulous tutorial also it is an inspirational one .Thanks a lot for the posting….

  • kamal

    It was the best one that I see until now.

    Tank you so much :)

  • chen

    It is so good and fabulous, but
    this form does not work with IE6.

  • Alan Fuller

    I wondering how we can have optional fields – a class called ‘optional’ and the check on field length also checks that $this.attr(‘class’).match(/optional/) is not true? Am I in the ballpark?

  • wespai

    nice plugin

  • Rilwis

    Cool. This registration form is very good for UX :). The effect is very smooth and pretty. Thanks for sharing.

  • Beben

    from usual to be unusual…:D
    awesome, thanks mate ^_^’

  • William

    A great tutorial…Again :)

  • Connor Crosby

    I love the design, and I like how it looks great with javascript turned off. Great job!

  • Fatih

    Hi,
    Thanks for this great tutorial.But i got a problem with form tag.When i change form tag to runat=server at ASP.NET,steps all checked even thought they’re empty.

  • paby

    as we say in Germany: GOIIIILLL

    thanks for sharing!!

    have fun – paby

  • Greg

    This really is great, especially after you fixed the display without JS on.

    @chen…its IE6, stop supporting it.

    The only problem I see is that the majority of users out there do not know they can hit tab to move through a form. You need (with JS turned on) a next button they can click on. Insert this with JS (or hide it normally and change the class so it shows with JS), so that they can click on it and this could be the best form I have seen in ages.

  • Bruno

    Amazing UI, inspirational Tutorial! Thanks a lot, I just have to develop a multi-part form like this, so… I’ll steal you the concept… :o) Thanks again!

  • Michel

    Excellent form!

    It works with JS disabled (which is great) but it works even better when JS is enabled in the browser… Good work! Sleek and elegant! :)

    //Sidenote: For some strange reason, TAB key works for moving from field to field and then to the next sub-page (and the next fields), but shift-tab doesn’t work in the backward direction. Perhaps I am missing something, though…

  • Federico Capoano

    Wow this is really cool.
    It’s a shame it doesn’t work on IE6.
    Does it work with Javascript disabled?

    If yes I might use it..

  • Matt

    This is outstanding, but there seems to be a height calculation error in IE7. The Confirm page shows up below the Settings information. Any ideas as to why?

  • dirk zaal

    Love the work you have put init,
    I actually leanred a lot of css (the shadows, round corners and gradients syntax)
    I really loved the validation concept but it sucks big time over here, but it will my challenge to fix and let that work for me…

    thanks for the hard work and sharing!

  • JZ

    Interesting read, thanks.

  • e11world

    This is super nice.
    Now I wonder if there’s a way we can integrate this with this tutorial from CSS-Tricks
    http://css-tricks.com/examples/SeminarRegTutorial/

  • Albert

    Nice!
    Would be nice to handle shift tab on the first element in the fieldset as well.

  • Andrea

    for MATT and the bug with IE7:
    just insert a blank div at the end of the form!

    bb and ty!

  • Flash

    Can i make some fields optional?

  • Matt

    Brilliant scripting and design. 10/10. Thanks for sharing.

  • ????

    just insert a blank div at the end of the form!

  • robert

    Hi! This sliding form rocks! But can i also initate the validation (red/green) for checkboxes?
    Thanks, Robert

  • lks

    great ! i have just added to my personal script list
    http://www.ajaxshake.com

  • Shevaa|WebDesignersBlog

    Wow… Cool Really Very nice Sliding Form Mary Lou… Thx for sharing man

  • alpaproductions

    Very nice script and most needed for me at the moment. Thank you very much!

  • Xcellence IT

    thats really awesome, and your tutorial comes with much easy language to understand it…

    thank you for sharing this with us.

  • bnibbler

    Whow! Amazing form that we have here…

    Thank you for posting this, I’ve learned a lot from your code and will certainly use this kind of form!

  • Kamil Brenk

    Really nice effect, I like it.

  • Filcuk

    Hello, it’s awesome, but i found a bug using Chrome 6 (in IE it was good)
    - When you fill email like “me” and not like “me@provider.com” it will not say error but you can’t send this form.

    I have to solve this with type=”text” instead of type=”email”

    Sorry 4 my english…

  • vinay

    This is awesome, looks clean, works well, occupies lesser space, I so want to use this on a project, could I please?

  • Mary Lou

    Of course! Cheers, ML

  • digof

    i want to change the size of steps any suggestion friends?? different slide different height

  • Saurabh shah

    This is very clean and awesome tutorial… Thanks for sharing.

  • Rahul Singh

    really nice.

    but in IE8, the height of text box is not same.but in firefox it is pretty well.

    plz suggest, how to get same look in IE8.

  • Web Dizajn

    Very Nice… thx from Sarajevo!

  • Michel

    This is a beauty….
    And great use for a shop…

  • Cody

    I’ve implemented this great jQuery form into a new book website that I’m doing, but having issues with it in IE7. I’ve read through the discussion comments and a couple have suggested putting a blank div tag at the end of the form…I have tried this and it still doesn’t fix the issue of the height. What it’s doing is putting the “Confirm” step below the second to last setps which makes the overall height twice as tall. Any suggestions as to how to fix this issue? I viewed the demo and it’s the same way.

    http://www.couragebeforeeverydanger.com/order/order.html

    Also is there a way to make it so not every single field is required? My form consist of a couple fields I don’t necessarily want to have required as some may not want to provide the information (i.e. phone number).

    Thanks,
    Cody

  • Sam

    Hi,

    Awesome form tutorial. Could you also explain how to integrate a form validation plugin like the Ketchup – http://demos.usejquery.com/ketchup-plugin/.

    Thanks.

  • Cody

    Do you not want all the fields required? I’ve figured out a way to allow you the ability to specify which fields get marked as required.

    On “sliding.form.js” find line 110. Then locate “find(‘:input:not(button)’).
    Change that section to “find(‘:input.required:not(button)’).

    Adding the “.required” puts a class that it searches for on the inputs. So on your form put [class="required"] – w/o brackets – on each of the fields/inputs you want to be required.

    Hope this helps you, I was sure glad to figure it out!

  • Roberto Schroeder

    Solution for optional

    update your .html
    add optional=”optional”

    update sliding.form.js
    add 3 lines
    112. var optional = $this.attr( ‘optional’ );
    113. if (optional != ‘optional’){
    122. }


    $(‘#formElem’).children(‘:nth-child(‘+ parseInt(step) +’)').find(‘:input:not(button)’).each(function(){
    var $this = $(this);
    var optional = $this.attr( ‘optional’ );
    if (optional != ‘optional’){
    var valueLength = jQuery.trim($this.val()).length;

    if(valueLength == ”){
    hasError = true;
    $this.css(‘background-color’,'#FFEDEF’);
    }
    else
    $this.css(‘background-color’,'#FFFFFF’);
    }
    });


    GOOD LUCKY

Follow this discussion

Join the discussion