Bootstrap Wizard Tutorial: How To Add A New Step

Published on: Jul 31 2016 by Anli

Bootstrap Wizard Tutorial - How To Add A New Step

After releasing this Bootstrap form wizard template a few weeks ago, called BootZard, a user left a comment asking how he could add a new step to it.

So, today’s article is a tutorial where I explain how you can easily add a new step to this form and I also show what is the algorithm used here.

Let’s begin!


Introduction

In this tutorial we will add a new step to the form where we will ask the users to create a “Security question”. As you can see, this is a multi-step registration form so it makes sense to add a question like that.

Here is a preview image of the final result:

Bootstrap Wizard Tutorial - New Step

For this customization we’ll need to make some small edits only to the HTML and CSS code. We’ll not touch the JavaScript code. However, below I’ll also show the JavaScript code so you have a general understanding of how the form works.

The HTML

The HTML code is in the “index.html” file. Here is the form’s code after we’ve made all the modifications (I explain them one by one below):

<form role="form" action="" method="post" class="f1">

    <h3>Register To Our App</h3>
    <p>Fill in the form to get instant access</p>
    <div class="f1-steps">
        <div class="f1-progress">
            <div class="f1-progress-line" data-now-value="12.5" data-number-of-steps="4" style="width: 12.5%;"></div>
        </div>
        <div class="f1-step active">
            <div class="f1-step-icon"><i class="fa fa-user"></i></div>
            <p>about</p>
        </div>
        <div class="f1-step">
            <div class="f1-step-icon"><i class="fa fa-key"></i></div>
            <p>account</p>
        </div>
        <div class="f1-step">
            <div class="f1-step-icon"><i class="fa fa-question"></i></div>
            <p>question</p>
        </div>
        <div class="f1-step">
            <div class="f1-step-icon"><i class="fa fa-twitter"></i></div>
            <p>social</p>
        </div>
    </div>

    <fieldset>
        <h4>Tell us who you are:</h4>
        <div class="form-group">
            <label class="sr-only" for="f1-first-name">First name</label>
            <input type="text" name="f1-first-name" placeholder="First name..." class="f1-first-name form-control" id="f1-first-name">
        </div>
        <div class="form-group">
            <label class="sr-only" for="f1-last-name">Last name</label>
            <input type="text" name="f1-last-name" placeholder="Last name..." class="f1-last-name form-control" id="f1-last-name">
        </div>
        <div class="form-group">
            <label class="sr-only" for="f1-about-yourself">About yourself</label>
            <textarea name="f1-about-yourself" placeholder="About yourself..." 
                                 class="f1-about-yourself form-control" id="f1-about-yourself"></textarea>
        </div>
        <div class="f1-buttons">
            <button type="button" class="btn btn-next">Next</button>
        </div>
    </fieldset>

    <fieldset>
        <h4>Set up your account:</h4>
        <div class="form-group">
            <label class="sr-only" for="f1-email">Email</label>
            <input type="text" name="f1-email" placeholder="Email..." class="f1-email form-control" id="f1-email">
        </div>
        <div class="form-group">
            <label class="sr-only" for="f1-password">Password</label>
            <input type="password" name="f1-password" placeholder="Password..." class="f1-password form-control" id="f1-password">
        </div>
        <div class="form-group">
            <label class="sr-only" for="f1-repeat-password">Repeat password</label>
            <input type="password" name="f1-repeat-password" placeholder="Repeat password..." 
                                class="f1-repeat-password form-control" id="f1-repeat-password">
        </div>
        <div class="f1-buttons">
            <button type="button" class="btn btn-previous">Previous</button>
            <button type="button" class="btn btn-next">Next</button>
        </div>
    </fieldset>

    <fieldset>
        <h4>Security question:</h4>
        <div class="form-group">
            <label class="sr-only" for="f1-question">Question</label>
            <input type="text" name="f1-question" placeholder="Question..." class="f1-question form-control" id="f1-question">
        </div>
        <div class="form-group">
            <label class="sr-only" for="f1-answer">Answer</label>
            <input type="text" name="f1-answer" placeholder="Answer..." class="f1-answer form-control" id="f1-answer">
        </div>
        <div class="f1-buttons">
            <button type="button" class="btn btn-previous">Previous</button>
            <button type="button" class="btn btn-next">Next</button>
        </div>
    </fieldset>

    <fieldset>
        <h4>Social media profiles:</h4>
        <div class="form-group">
            <label class="sr-only" for="f1-facebook">Facebook</label>
            <input type="text" name="f1-facebook" placeholder="Facebook..." class="f1-facebook form-control" id="f1-facebook">
        </div>
        <div class="form-group">
            <label class="sr-only" for="f1-twitter">Twitter</label>
            <input type="text" name="f1-twitter" placeholder="Twitter..." class="f1-twitter form-control" id="f1-twitter">
        </div>
        <div class="form-group">
            <label class="sr-only" for="f1-google-plus">Google plus</label>
            <input type="text" name="f1-google-plus" placeholder="Google plus..." class="f1-google-plus form-control" id="f1-google-plus">
        </div>
        <div class="f1-buttons">
            <button type="button" class="btn btn-previous">Previous</button>
            <button type="submit" class="btn btn-submit">Submit</button>
        </div>
    </fieldset>

</form>

If you compare the two versions of the form, before and after the modifications, you’ll see that:

First, we change the attributes of the progress bar: the “data-now-value” attribute from “16.66” becomes “12.5”, “data-number-of-steps” from “3” becomes “4” and “style” from “width: 16.66%;” becomes “width: 12.5%;”.

<div class="f1-progress">
    <div class="f1-progress-line" data-now-value="12.5" data-number-of-steps="4" style="width: 12.5%;"></div>
</div>

The formula here is: 100 / number of steps / 2 (100 divided by the number of steps divided by 2). In our case “100 / 4 / 2” is 12.5.

Second, we add the new step’s icon and text in the progress bar (between “account” and “social”):

<div class="f1-step">
    <div class="f1-step-icon"><i class="fa fa-question"></i></div>
    <p>question</p>
</div>

An important note that should be mentioned here, is that you should try to not add too many steps, because the usability and visibility in mobile devices will not be very good.

If you really can’t reduce the number of steps, you can try other solutions like, for example, hide the progress bar and the icons with CSS in small screens.

Third, we add the new step “Security question” which has two text fields and is placed between the steps “Set up your account” and “Social media profiles”. It is grouped in a “fieldset” tag, just like the other steps:

<fieldset>
    <h4>Security question:</h4>
    <div class="form-group">
        <label class="sr-only" for="f1-question">Question</label>
        <input type="text" name="f1-question" placeholder="Question..." class="f1-question form-control" id="f1-question">
    </div>
    <div class="form-group">
        <label class="sr-only" for="f1-answer">Answer</label>
        <input type="text" name="f1-answer" placeholder="Answer..." class="f1-answer form-control" id="f1-answer">
    </div>
    <div class="f1-buttons">
        <button type="button" class="btn btn-previous">Previous</button>
        <button type="button" class="btn btn-next">Next</button>
    </div>
</fieldset>

The CSS

You can find the CSS code in the files “style.css” and “form-elements.css” in “assets/css”. In this case we have to only make a small modification in “style.css”:

.f1-step { position: relative; float: left; width: 25%; padding: 0 5px; }

We have changed the width value from “33.333333%” to “25%”.

Now the form with its new step is ready and we don’t have to make other changes. But, as I said above, below I’m also going to show and briefly explain the JavaScript code used here.

The JavaScript

The JavaScript code is in the “scripts.js” file in “assets/js”.

function scroll_to_class(element_class, removed_height) {
    var scroll_to = $(element_class).offset().top - removed_height;
    if($(window).scrollTop() != scroll_to) {
        $('html, body').stop().animate({scrollTop: scroll_to}, 0);
    }
}

function bar_progress(progress_line_object, direction) {
    var number_of_steps = progress_line_object.data('number-of-steps');
    var now_value = progress_line_object.data('now-value');
    var new_value = 0;
    if(direction == 'right') {
        new_value = now_value + ( 100 / number_of_steps );
    }
    else if(direction == 'left') {
        new_value = now_value - ( 100 / number_of_steps );
    }
    progress_line_object.attr('style', 'width: ' + new_value + '%;').data('now-value', new_value);
}

jQuery(document).ready(function() {

    /*
        Fullscreen background
    */
    $.backstretch("assets/img/backgrounds/1.jpg");

    $('#top-navbar-1').on('shown.bs.collapse', function(){
        $.backstretch("resize");
    });
    $('#top-navbar-1').on('hidden.bs.collapse', function(){
        $.backstretch("resize");
    });

    /*
        Form
    */
    $('.f1 fieldset:first').fadeIn('slow');

    $('.f1 input[type="text"], .f1 input[type="password"], .f1 textarea').on('focus', function() {
        $(this).removeClass('input-error');
    });

    // next step
    $('.f1 .btn-next').on('click', function() {
        var parent_fieldset = $(this).parents('fieldset');
        var next_step = true;
        // navigation steps / progress steps
        var current_active_step = $(this).parents('.f1').find('.f1-step.active');
        var progress_line = $(this).parents('.f1').find('.f1-progress-line');

        // fields validation
        parent_fieldset.find('input[type="text"], input[type="password"], textarea').each(function() {
            if( $(this).val() == "" ) {
                $(this).addClass('input-error');
                next_step = false;
            }
            else {
                $(this).removeClass('input-error');
            }
        });
    	// fields validation

        if( next_step ) {
            parent_fieldset.fadeOut(400, function() {
                // change icons
                current_active_step.removeClass('active').addClass('activated').next().addClass('active');
                // progress bar
                bar_progress(progress_line, 'right');
                // show next step
                $(this).next().fadeIn();
                // scroll window to beginning of the form
                scroll_to_class( $('.f1'), 20 );
            });
        }

    });

    // previous step
    $('.f1 .btn-previous').on('click', function() {
        // navigation steps / progress steps
        var current_active_step = $(this).parents('.f1').find('.f1-step.active');
        var progress_line = $(this).parents('.f1').find('.f1-progress-line');

        $(this).parents('fieldset').fadeOut(400, function() {
            // change icons
            current_active_step.removeClass('active').prev().removeClass('activated').addClass('active');
            // progress bar
            bar_progress(progress_line, 'left');
            // show previous step
            $(this).prev().fadeIn();
            // scroll window to beginning of the form
            scroll_to_class( $('.f1'), 20 );
        });
    });

    // submit
    $('.f1').on('submit', function(e) {

        // fields validation
        $(this).find('input[type="text"], input[type="password"], textarea').each(function() {
            if( $(this).val() == "" ) {
                e.preventDefault();
                $(this).addClass('input-error');
            }
            else {
                $(this).removeClass('input-error');
            }
        });
        // fields validation

    });

});

At the beginning of the file we have two functions that we use in other parts of the code when needed.

The first function “scroll_to_class” is used to scroll the browser’s window to the beginning of the form when the user changes the step (previous or next).

The various steps of the form may have varying input fields resulting in different form heights, so we use this function to make sure that the user always sees the beginning of the form when moved to a new step.

The second function “bar_progress” is used to move the progress bar to the left or right when the step changes.

The remaining code is all commented so it’s not very difficult to understand it.

When it comes to the form’s behaviour, we have 3 main events: the user clicks the “Next” button, the “Previous” button or the “Submit” button.

Let’s see what happens in the case of the “Next” button. The other two events are very similar.

// next step
$('.f1 .btn-next').on('click', function() {
    var parent_fieldset = $(this).parents('fieldset');
    var next_step = true;
    // navigation steps / progress steps
    var current_active_step = $(this).parents('.f1').find('.f1-step.active');
    var progress_line = $(this).parents('.f1').find('.f1-progress-line');

    // fields validation
    parent_fieldset.find('input[type="text"], input[type="password"], textarea').each(function() {
        if( $(this).val() == "" ) {
            $(this).addClass('input-error');
            next_step = false;
        }
        else {
            $(this).removeClass('input-error');
        }
    });
    // fields validation

    if( next_step ) {
        parent_fieldset.fadeOut(400, function() {
            // change icons
            current_active_step.removeClass('active').addClass('activated').next().addClass('active');
            // progress bar
            bar_progress(progress_line, 'right');
            // show next step
            $(this).next().fadeIn();
            // scroll window to beginning of the form
            scroll_to_class( $('.f1'), 20 );
        });
    }

});

First we create all the variables we need where we store various DOM elements, etc.

Next we validate the form. The validation here is very simple, we just check if any field is empty. In that case we add an “input-error” class to the input field and set the variable “next_step” to “false”.

If there are not empty fields, we proceed with the next step: we hide the current fields, change the icons’ style at the top, move the progress bar to the right, show the input fields of the next step, scroll the browser’s window to the beginning of the form.

As we mentioned above, we only check for empty fields. Depending on the types of forms that you may have in your projects, you may need to add other rules to the validator.

Another thing to keep in mind: this is a front-end validator and you might also need back-end validation in your projects. You can implement it in different ways depending on the project requirements.

Conclusion

We just learned how to add a new step to our Bootstrap form wizard. We used some HTML code and made a small modification to the CSS file. Below you can preview the form and download the source files. Let me know if you have any question or suggestion in the comments.

VIEW DEMO

DOWNLOAD: Bootstrap Wizard Tutorial - New Step (535)

Want More Forms?

Try Marco. It comes with 30+ forms:

Marco Template: Login Forms

Marco Template: Registration Forms

Filed under: Tutorials

3 Comments So Far

  1. Kristian Bech says:

    This source code, how is the license for this? In the text it says customize and use as you like.
    I just want to make sure. 🙂

  2. Vikrant says:

    Nice script. 🙂
    I have a query; How to add validation for Checkbox. Trying to add in // fields validation
    section. but it not applying validation please suggest.

  3. Matt says:

    I’ve tried adding more than 4 steps (max 6), updated the necessary steps and CSS but it won’t go further than 4 steps. Since there is no editing of the javascript, is there somewhere else that might be affecting the additional steps? The progress line and step icons indicate the additional steps but the form won’t proceed past the 4th step. Any ideas?

Leave a Reply