Tutorials
Tutorials

Multi-Step Signup Form Using jQuery and CSS3


View Demo    Download

 

Signing up a user for your product or service is a very tough job to do. So, why not to give a pleasant onboarding experience to our new users? To make this toughest job easy, we will be creating a multi-step signup form using simple jQuery and CSS3.

Creating a Structure

Our HTML structure consists of 3 main components. First is a form element, form#msform which holds two other elements, ul#progressbar and fieldset

<form id="msform">
        <!-- progressbar -->
        <ul id="progressbar">
          <li class="active">Account Setup</li>
          <li>Social Profiles</li>
          <li>Personal Details</li>
        </ul>
        <!-- fieldsets -->
        <fieldset>
          <img class="logo" src="img/designgiri-logo.png">
          <h2 class="fs-title">Sign up</h2>
          <h3 class="fs-subtitle">Let’s have a new beginning. Sign up for new you</h3>
          <input type="text" name="username" placeholder="Username" />
          <input type="text" name="email" placeholder="Email" />
          <input type="password" name="pass" placeholder="Password" />
          <input type="password" name="cpass" placeholder="Confirm Password" />
          <input type="button" name="next" class="next action-button" value="Next" />
        </fieldset>
        <fieldset>
          <img class="logo" src="img/designgiri-logo.png">
          <h2 class="fs-title">Social Profiles</h2>
          <input type="text" name="twitter" placeholder="Twitter" />
          <input type="text" name="facebook" placeholder="Facebook" />
          <input type="text" name="gplus" placeholder="Google Plus" />
          <input type="button" name="previous" class="previous action-button" value="Previous" />
          <input type="button" name="next" class="next action-button" value="Next" />
        </fieldset>
        <fieldset>
          <img class="logo" src="img/designgiri-logo.png">
          <h2 class="fs-title">Personal Details</h2>
          <input type="text" name="fname" placeholder="First Name" />
          <input type="text" name="lname" placeholder="Last Name" />
          <input type="text" name="phone" placeholder="Phone" />
          <textarea name="address" placeholder="Address"></textarea>
          <input type="button" name="previous" class="previous action-button" value="Previous" />
          <input type="submit" name="submit" class="submit action-button" value="Submit" />
        </fieldset>
        <fieldset>
          <img class="logo" src="img/designgiri-logo.png">
          <h2 class="fs-title">Personal Details</h2>
          <input type="text" name="fname" placeholder="First Name" />
          <input type="text" name="lname" placeholder="Last Name" />
          <input type="text" name="phone" placeholder="Phone" />
          <textarea name="address" placeholder="Address"></textarea>
          <input type="button" name="previous" class="previous action-button" value="Previous" />
          <input type="submit" name="submit" class="submit action-button" value="Submit" />
        </fieldset>
        <p>Already have an account? <a href="#">Sign in</a></p>
      </form>

Styling the elements

First, we will be styling the form element and the fieldset. Remember that, only one fieldset will be visible at a time out of three.

/* Form styles */
#msform {
	width: 400px;
	margin: 50px auto;
	text-align: center;
	position: relative;
}
#msform fieldset {
	background: #fff;
	border: 0 none;
	border-radius: 5px;
	box-shadow: 0 0 30px 1px rgba(0, 0, 0, 0.1);
	padding: 20px;
	box-sizing: border-box;
	width: 80%;
	margin: 0 10% 20px;
	
	/*stacking fieldsets above each other*/
	position: relative;
}

/* Hide all except first fieldset */
#msform fieldset:not(:first-of-type) {
	display: none;
}
img.logo {
	max-width: 120px;
	margin-bottom: 20px;
}
#msform p {
	color: #8b9ab0;
	font-size: 12px;
}

Inputs, buttons and other form elements

/* Inputs */
#msform input, #msform textarea {
	padding: 12px 15px;
	border: 1px solid transparent;
	border-radius: 3px;
	margin-bottom: 10px;
	background-color: #eef5ff;
	width: 100%;
	box-sizing: border-box;
	font-family: montserrat;
	color: #333;
	font-size: 14px;
	font-family: inherit;
}
#msform input:focus, #msform textarea:focus {
	outline: none;
	border-color: #7bbdf3;
}

/* Buttons */
#msform .action-button {
	width: 49%;
	text-transform: uppercase;
	background: #e74c3c;
	font-weight: bold;
	color: white;
	border: 0 none;
	border-radius: 3px;
	cursor: pointer;
	padding: 12px 5px;
	margin: 10px 0;
	font-size: 16px;
	display: inline-block;
	-webkit-transition: all 0.2s;
	-moz-transition: all 0.2s;
	transition: all 0.2s;
}
#msform .previous.action-button {
	background: #7bbdf3;
}

#msform .action-button:hover, #msform .action-button:focus {
	box-shadow: 0 10px 30px 1px rgba(0, 0, 0, 0.2);
}

/* Headings */
.fs-title {
	font-size: 26px;
	font-weight: 200;
	color: #434a54;
	margin-bottom: 20px;
}
.fs-subtitle {
	font-weight: 400;
	color: #434a54;
	margin-bottom: 20px;
}

Let’s add some style to progress-bar and and progress-bar connectors

/* Progressbar */
#progressbar {
	margin-bottom: 30px;
	overflow: hidden;
	/*CSS counters to number the steps*/
	counter-reset: step;
}
#progressbar li {
	list-style-type: none;
	color: #8b9ab0;
	text-transform: uppercase;
	font-size: 9px;
	width: 33.33%;
	float: left;
	position: relative;
}
#progressbar li.active {
	color: #e74c3c;
}
#progressbar li:before {
	content: counter(step);
	counter-increment: step;
	width: 20px;
	line-height: 20px;
	display: block;
	font-size: 10px;
	color: #333;
	background: white;
	border-radius: 3em;
	margin: 0 auto 5px auto;
}

/* Progressbar connectors */
#progressbar li:after {
	content: '';
	width: 100%;
	height: 2px;
	background: white;
	position: absolute;
	left: -50%;
	top: 9px;
	z-index: -1;
}
#progressbar li:first-child:after {
	/* connector not needed before the first step */
	content: none; 
}

/* Marking active/completed steps green */
/*The number of the step and the connector before it = green*/
#progressbar li.active:before,  #progressbar li.active:after{
	background: #23cf5f;
	color: white;
}

Event handling

We will be handling two important events. One will be on click of next and second will be on click of a previous button.

//jQuery time
var current_fs, next_fs, previous_fs; //fieldsets
var left, opacity, scale; //fieldset properties which we will animate
var animating; //flag to prevent quick multi-click glitches

$(".next").click(function(){
	if(animating) return false;
	animating = true;
	
	current_fs = $(this).parent();
	next_fs = $(this).parent().next();
	
	//activate next step on progressbar using the index of next_fs
	$("#progressbar li").eq($("fieldset").index(next_fs)).addClass("active");
	
	//show the next fieldset
	next_fs.show(); 
	//hide the current fieldset with style
	current_fs.animate({opacity: 0}, {
		step: function(now, mx) {
			//as the opacity of current_fs reduces to 0 - stored in "now"
			//1. scale current_fs down to 80%
			scale = 1 - (1 - now) * 0.2;
			//2. bring next_fs from the right(50%)
			left = (now * 50)+"%";
			//3. increase opacity of next_fs to 1 as it moves in
			opacity = 1 - now;
			current_fs.css({
				'transform': 'scale('+scale+')',
				'position': 'absolute'
			});
			next_fs.css({'left': left, 'opacity': opacity});
		}, 
		duration: 800, 
		complete: function(){
			current_fs.hide();
			animating = false;
		}, 
		//this comes from the custom easing plugin
		easing: 'easeInOutBack'
	});
});

$(".previous").click(function(){
	if(animating) return false;
	animating = true;
	
	current_fs = $(this).parent();
	previous_fs = $(this).parent().prev();
	
	//de-activate current step on progressbar
	$("#progressbar li").eq($("fieldset").index(current_fs)).removeClass("active");
	
	//show the previous fieldset
	previous_fs.show(); 
	//hide the current fieldset with style
	current_fs.animate({opacity: 0}, {
		step: function(now, mx) {
			//as the opacity of current_fs reduces to 0 - stored in "now"
			//1. scale previous_fs from 80% to 100%
			scale = 0.8 + (1 - now) * 0.2;
			//2. take current_fs to the right(50%) - from 0%
			left = ((1-now) * 50)+"%";
			//3. increase opacity of previous_fs to 1 as it moves in
			opacity = 1 - now;
			current_fs.css({'left': left});
			previous_fs.css({'transform': 'scale('+scale+')', 'opacity': opacity});
		}, 
		duration: 800, 
		complete: function(){
			current_fs.hide();
			animating = false;
		}, 
		//this comes from the custom easing plugin
		easing: 'easeInOutBack'
	});
});

$(".submit").click(function(){
	return false;
})

We are done here! 🙂

You can use this tutorial for checkout process also. Do let me know in case you have any query or feedback by commenting on this post.

Do check out the demo.

View Demo    Download

Find this project on GitHub 

A Product Designer. Currently designing and developing digital products for founders and startups. Can speak HTML5, CSS3 and JavaScript (sometimes English too).

View Comments
There are currently no comments.