Long forms are intimidating. An easy way to increase <form>
conversions is by using conditional fields. Conditional fields are hidden by default and appear when they become relevant. They are a great way to make forms shorter and more personalized. For example, suppose you request customer feedback. Here is a demo with conditional fields, try it out:
Demo
This article will teach you how to create forms with conditional fields like the above example. We'll be using the Bootstrap CSS framework and jQuery. However, the concepts you learn could be implemented just as well with unstyled HTML forms and plain old JavaScript
Form Structure
Notice how the labels and fields in the above example change based on the user's input. In other words, later fields are conditional on earlier fields. Here is an example tree, illustrating these relationships:
This form includes 5 fields. However, an individual submission will contain at most 3 fields: a rating field (always), a testimonial field (sometimes), and one feedback field (at most). Form fields are identified by their name in the HTML. The form structure will look like this:
rating
testimonial
(ifrating
is 'Excellent')- feedback
feedback_bad
(ifrating
is 'Bad' or 'Fair')feedback_ok
(ifrating
is 'Good' or 'Very Good')feedback_good
(iftestimonial
is 'yes' andrating
is 'Excellent')
Step 1: Create a Static Form
The first step is simply to create a form that includes all possible fields. We'll be using Bootstrap CSS for our form. Hand code the form using the Bootstrap Form syntax or use our Bootstrap Form Builder to create the HTML for you. Give the form the id #live_form
. Your form will be really long. At this stage, our form looks like this:
<form id="live_form">
<div class="form-group">
<label class="control-label ">
How would you rate your experience with us?
</label>
<div>
<div class="radio">
<label class="radio">
<input name="rating" type="radio" value="Bad"/>
Bad
</label>
</div>
<div class="radio">
<label class="radio">
<input name="rating" type="radio" value="Fair"/>
Fair
</label>
</div>
<div class="radio">
<label class="radio">
<input name="rating" type="radio" value="Good"/>
Good
</label>
</div>
<div class="radio">
<label class="radio">
<input name="rating" type="radio" value="Very Good"/>
Very Good
</label>
</div>
<div class="radio">
<label class="radio">
<input name="rating" type="radio" value="Excellent"/>
Excellent
</label>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label" for="feedback_bad">
We're sorry to hear you had a bad experience. What went wrong?
</label>
<textarea class="form-control" cols="40" id="feedback_bad" name="feedback_bad" rows="10"></textarea>
</div>
<div class="form-group">
<label class="control-label" for="feedback_ok">
Please tell us what you liked and how we can improve:
</label>
<textarea class="form-control form-control" cols="40" id="feedback_ok" name="feedback_ok" rows="10"></textarea>
</div>
<div class="form-group" id="div_testimonial">
<div>
<label class="control-label " for="testimonial">
Wonderful! We're so glad to hear that. Would you be willing to write a customer comment for our website?
</label>
<div>
<label class="radio-inline">
<input name="testimonial" type="radio" value="yes"/>
Sure!
</label>
<label class="radio-inline">
<input name="testimonial" type="radio" value="no"/>
I'd rather not.
</label>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label " for="feedback_great">
Thank you so much! Please leave your testimonial here:
</label>
<textarea class="form-control" cols="40" id="feedback_great" name="feedback_great" rows="10"></textarea>
</div>
<div class="form-group" id="thanks_anyway">
<label class="control-label">
No problem, thanks for being a customer!
</label>
</div>
<div class="form-group">
<button class="btn btn-primary " name="submit" type="submit">
Submit
</button>
</div>
</form>
Step 2: Hide All Conditional Fields
Only the first field, rating
, needs to be visible when the form loads. The rest of the fields should be hidden. We can hide a field by applying one line of CSS:
display: none;
to each conditional field's wrapper <div>
. In Bootstrap, this can be accomplished with the class .hidden
.
Here is how you'd hide the field named feedback_bad
:
<div class="form-group hidden">
<label class="control-label" for="feedback_bad">
We're sorry to hear you had a bad experience. What went wrong?
</label>
<textarea class="form-control" cols="40" id="feedback_bad" name="feedback_bad" rows="10"></textarea>
</div>
Hiding all fields, gives us the following shorter (but still static) form:
<form id="live_form">
<div class="form-group">
<label class="control-label ">
How would you rate your experience with us?
</label>
<div class="">
<div class="radio">
<label class="radio">
<input name="rating" type="radio" value="Bad"/>
Bad
</label>
</div>
<div class="radio">
<label class="radio">
<input name="rating" type="radio" value="Fair"/>
Fair
</label>
</div>
<div class="radio">
<label class="radio">
<input name="rating" type="radio" value="Good"/>
Good
</label>
</div>
<div class="radio">
<label class="radio">
<input name="rating" type="radio" value="Very Good"/>
Very Good
</label>
</div>
<div class="radio">
<label class="radio">
<input name="rating" type="radio" value="Excellent"/>
Excellent
</label>
</div>
</div>
</div>
<div class="form-group hidden">
<label class="control-label" for="feedback_bad">
We're sorry to hear you had a bad experience. What went wrong?
</label>
<textarea class="form-control" cols="40" id="feedback_bad" name="feedback_bad" rows="10"></textarea>
</div>
<div class="form-group hidden">
<label class="control-label" for="feedback_ok">
Please tell us what you liked and how we can improve:
</label>
<textarea class="form-control form-control" cols="40" id="feedback_ok" name="feedback_ok" rows="10"></textarea>
</div>
<div class="form-group hidden" id="div_testimonial">
<div>
<label class="control-label " for="testimonial">
Wonderful! We're so glad to hear that. Would you be willing to write a customer comment for our website?
</label>
<div>
<label class="radio-inline">
<input name="testimonial" type="radio" value="yes"/>
Sure!
</label>
<label class="radio-inline">
<input name="testimonial" type="radio" value="no"/>
I'd rather not.
</label>
</div>
</div>
</div>
<div class="form-group hidden">
<label class="control-label " for="feedback_great">
Thank you so much! Please leave your testimonial here:
</label>
<textarea class="form-control" cols="40" id="feedback_great" name="feedback_great" rows="10"></textarea>
</div>
<div class="form-group hidden" id="thanks_anyway">
<label class="control-label">
No problem, thanks for being a customer!
</label>
</div>
<div class="form-group">
<button class="btn btn-primary " name="submit" type="submit">
Submit
</button>
</div>
</form>
Step 3: Reveal Fields with jQuery as Needed
Now, we need to write some jQuery/JavaScript to reveal conditional fields as the form is filled out. In a nutshell, we'll
- Download jQuery and add it to the webpage
Wait until the page finishes loading
$( document ).ready(function() { //script here }
Select the "independent" field elements
rating
andtestimonial
var rating = $('#live_form input:radio[name=rating]'); var testimonial = $('#live_form input:radio[name=testimonial]');
Select the "dependent" field wrapper elements
var bad = $('#live_form textarea[name="feedback_bad"]').parent(); var ok = $('#live_form textarea[name="feedback_ok"]').parent(); var great = $('#live_form textarea[name="feedback_great"]').parent(); var testimonial_parent = $('#live_form #div_testimonial'); var thanks_anyway = $('#live_form #thanks_anyway');
- When "independent" fields change, unhide the relevant "dependent" field wrapper element/s. This is achieved by using the jQuery methods
removeClass
andaddClass
with.hidden
.
The script in its entirety is below. Read through it slowly to understand what is going on:
$( document ).ready(function() { //wait until body loads
var testimonial_ok=false; //keeps track of whether the testimonial box is filled out
//Inputs that determine what fields to show
var rating = $('#live_form input:radio[name=rating]');
var testimonial=$('#live_form input:radio[name=testimonial]');
//Wrappers for all fields
var bad = $('#live_form textarea[name="feedback_bad"]').parent();
var ok = $('#live_form textarea[name="feedback_ok"]').parent();
var great = $('#live_form textarea[name="feedback_great"]').parent();
var testimonial_parent = $('#live_form #div_testimonial');
var thanks_anyway = $('#live_form #thanks_anyway');
var all=bad.add(ok).add(great).add(testimonial_parent).add(thanks_anyway); //shortcut for all wrapper elements
rating.change(function(){ //when the rating changes
var value=this.value;
all.addClass('hidden'); //hide everything and reveal as needed
if (value == 'Bad' || value == 'Fair'){
bad.removeClass('hidden'); //show feedback_bad
}
else if (value == 'Good' || value == 'Very Good'){
ok.removeClass('hidden'); //show feedback_ok
}
else if (value == 'Excellent'){
testimonial_parent.removeClass('hidden'); //show testimonial question
//if testimonial has already been answered
if (testimonial_ok == 'yes'){great.removeClass('hidden');}
else if (testimonial_ok == 'no'){thanks_anyway.removeClass('hidden');}
}
});
testimonial.change(function(){
//hide all except testimonial question
all.addClass('hidden');
testimonial_parent.removeClass('hidden');
testimonial_ok=this.value;
if (testimonial_ok == 'yes'){ //if user willing to write testimonial
great.removeClass('hidden'); //show feedback_great
}
else{
thanks_anyway.removeClass('hidden'); //show thanks message
}
});
});
Some important points to keep in mind:
- The code must be robust to users changing their mind.
testimonial_ok
keeps track of the whether the testimonial field has been filled out to account for this possibility. - There are multiple
radio
buttons. So, we are actually selecting multiple elements and attaching events to each element.