Fancy Sliding Form with jQuery

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 […]

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!

Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.

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!

Message from TestkingGet professional testking ccda training to learn about critical web design tools and become expert in web design using testking mcts tutorials and testking mcitp live demos.

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

Stay in the loop: Get your dose of frontend twice a week

Fresh news, inspo, code demos, and UI animations—zero fluff, all quality. Make your Mondays and Thursdays creative!

Feedback 183

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

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

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

    Great commenting/instructions in the coding as well.

  4. 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!

  5. 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.

    • @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

  6. @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”

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

  8. 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.

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

  10. 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?

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

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

  13. 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.

  14. 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.

  15. 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!

  16. 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…

  17. 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..

  18. 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?

  19. 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!

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

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

    bb and ty!

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

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

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

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

    thank you for sharing this with us.

  26. 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!

  27. 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…

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

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

  30. 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.