How to create multi-step product options in WooCommerce

If you have a complex WooCommerce product with many different options, it may be a good idea to split those options in a multi-step form. This tutorial will show how to achieve multi-step product options in your WooCommerce store.

What we’re building

We’ll create product options, split into multiple steps. A progress bar indicates how far the user is in the process before being able to add the product to their cart.

What you’ll need

  • A store with WooCommerce (3.4.0 or higher) installed and configured. We assume this is already done on your end but just in case it’s not, you can read this article to get started with WooCommerce.
  • Our Advanced Product Fields for WooCommerce plugin. The plugin has a free version, but for this tutorial, you’ll need the premium version. This plugin is capable of adding options to your product.

Let’s get started!

1. Configure the options on your product

If you have our plugin up & running, edit your WooCommerce product and find the Custom fields section under Product Data:

custom fields tab in woocommerce product

Here, you can add all options that belong to your product. The important part is to wrap your options in different sections. Each section will represent one step on your product page.

You can add sections by clicking New Field and then choosing Section and Section End as field types. Adding fields to a section is as simple as dragging them between the Section and Section End fields.

Make sure to add a class name to each section, called “step”. You can do that in the section field settings:

Below is an example of 2 sections each containing a few options:

In a later step, we’ll transform these sections into steps with CSS.

2. Add progress bar & buttons

Next, we need to add some HTML to display a progress bar and buttons to navigate between the steps. That’s done by simply copy/pasting the code below into your active (child) theme’s functions.php file:

add_action('wapf_before_wrapper', 'wapf_before_wrapper');
function wapf_before_wrapper($product) {
	?>
	<div class="wapf-progress">
		<div class="wapf-progress-bar"></div>
		<div class="wapf-progress-steps"></div>
	</div>
	<?php
}

add_action('wapf_before_product_totals', 'wapf_before_product_totals');
function wapf_before_product_totals($product){
	?>
	<div class="wapf_step_buttons">
		<button class="button wapf_btn_prev" style="display:none">Previous</button>
		<button class="button wapf_btn_next">Next</button>
	</div>
	<?php
}

3. Add styling

In this step, we’ll add CSS to style the progress bar, buttons, and sections. Add the CSS below to your theme via Appearance > Customize > Additional CSS.

Please note the CSS may be a little different for your WordPress theme, but it should be pretty close. I’ve added some comments in bold that may be useful to look at.

div.quantity, .woocommerce .button[name=add-to-cart] {
    display:none; /*Hide Add to Cart button until last step*/
}

.wapf-field-group .step{
    display:none;
}

.wapf-field-group .step:first-child{
    display:flex;
}
.wapf-wrapper{
    border-radius: 4px;
    border: 1px solid #ededed;
    padding: 15px 20px;
    margin-bottom:20px;
}
.wapf_step_buttons{
    margin-bottom:20px;
    overflow:hidden;
}
.wapf_btn_next{
    float:right !important;
}
.wapf-progress{
    position:relative;
    max-width:450px;
    margin: 0 auto;
}
.wapf-progress:before, .wapf-progress-bar{
    content:'';
    position:absolute;
    height:3px;
    width:100%;
    background:#ededed;
    top:14px;
}
.wapf-progress-steps{
    margin-bottom: 30px;
    overflow: hidden;
    counter-reset: step;
    display: flex;
    justify-content: space-between;
}
.wapf-progress-steps div{
    position:relative;
}
.wapf-progress-steps div:before{
    content: counter(step);
    counter-increment: step;
    width: 30px;
    height:30px;
    font-size:16px;
    line-height:30px;
    border-radius:50%;
    text-align:center;
    display: block;
    font-size: 10px;
    background: #ededed;
}
.wapf-progress-steps div.active:before{
    background:#f0632b; /*The finished step color. Feel free to change*/
    color:white;
}

.wapf-progress-bar{
    background:#f0632b; /*The finished step color. Feel free to change*/
    width:0%;
}

This CSS will change the appearance for all single product pages though. If you only have a few products that will have a multi-step form, this CSS should be changed to only affect those products. This can easily be done if you know your product ID.

Make things dynamic

By now, you’ll see the multi-step form is displayed nicely on your Woo product page. But it needs some Javascript logic to make things work. Add the following code in your (child) theme’s functions.php file:

add_action('wp_footer','wapf_steps_script');
function wapf_steps_script(){
	?>
	<script>
	jQuery(document).ready(function() {
		
		var steps = jQuery('.wapf-section.step');
		var maxSteps = steps.length;
		var $prev = jQuery('.wapf_btn_prev');
		var $next = jQuery('.wapf_btn_next');
		var $stepList = jQuery('.wapf-progress-steps');
		var $bar = jQuery('.wapf-progress-bar');
		var $cart = jQuery('div.quantity,[name="add-to-cart"]');
		var currentStep = 1;
		var $form =	jQuery('form.cart');
		
		for(var i = 1; i <= maxSteps;i++) {
			var $div = jQuery('<div>');
			if(i === 1)
				$div.addClass('active');
			$stepList.append($div);
		}
								
		var post = function(e) {
			var max = $stepList.find('div:visible').length;

			e.preventDefault();

			steps.hide();
			steps.eq(currentStep-1).show();
			
			$stepList.find('div').removeClass('active').eq(currentStep).prevAll().addClass('active');
			if(currentStep == max) {
				$stepList.find('div').addClass('active');
				$cart.show();
			} else {
				$cart.hide();
			}
			
			$bar.css('width', (currentStep-1)*(100/(max-1))+'%');
			
			$prev.hide();
			$next.hide();
			if(currentStep < max)
				$next.show();
			if(currentStep > 1)
				$prev.show();
		}
		
		var isValid = function() {
			
			var $current = steps.eq(currentStep-1);
			var $inputs = $current.find(':input');
			
			for(var i = 0;i<$inputs.length;i++) {
				if(!$inputs[i].checkValidity())
					return false;
			}
			
			return true;
		}
		
		$prev.on('click', function(e) {
			currentStep--;
			post(e);
		});
		
		$next.on('click', function(e) {
			var $current = steps.eq(currentStep-1);
			var valid = isValid();
			if(isValid()) {
				currentStep++;
				post(e);
			}
		});
		
		jQuery(document).on('wapf/dependencies', function(){
			$stepList.find('div').removeClass('wapf-hide');
			steps.each(function(i,s){
				var $s = jQuery(s);
				if($s.hasClass('wapf-hide'))
					$stepList.find('div:eq('+i+')').addClass('wapf-hide');
			});
		});
		
	});
	</script>
	<?php
}

The script will make sure the progress bar is updated correctly, the "previous" and "next" buttons do their work, and the correct section is shown at any time.

That's it! Now you should have a working multi-step product options form!

Please reach out to us via our livechat or contact page if anything is unclear or you need help with CSS or Javascript.