Skip to content

Add user displayed completion tracking to your Collapsible Sections

One of the most requested features for our Collapsible Sections add-on for Gravity Forms has been the ability to add user-displayed completion tracking to Collapsible Sections.

Good news — this tutorial introduces a lightweight JavaScript snippet that does just that. The script monitors each collapsible section and checks whether the fields within that section have a value. If they do, the section is marked as “complete” with a visual indicator.

Now, a quick note: this isn’t performing any validation on the fields — it’s not checking for correct formats or other requirements. It simply looks for whether the fields in the section contain any value. Once they do, the section gets flagged as completed.

It’s a simple, user-friendly way to help guide users through long forms by giving them a sense of progress as they go.

Add user displayed completion tracking to your Collapsible Sections
Add user displayed completion tracking to your Collapsible Sections.

What you’ll need

Track Section Completion in Collapsible Sections

To get started with this tutorial, you’ll need a few essentials. First, make sure you have Gravity Forms installed and active on your WordPress site. Next, you’ll need the Collapsible Sections add-on by JetSloth, which allows you to group fields into toggleable sections. While not required, we recommend using Code Chest by Gravity Wiz or another method to safely inject custom JavaScript into your site. Lastly, you’ll use a simple JavaScript snippet provided below that enables the functionality.

Gravity Forms
A copy of Collapsible Section
Code Chest by Gravity Wiz to add the Javascript or CSS (optional)
Supplied Custom Javascript below

Add the tracking JavaScript

Add the below JavaScript to your form using the Code Chest plugin. This JavaScript code snippet does all the heavy lifting we’ll need. So just copy and paste it over to your form code chest and you’re good to go!

const CS_CHECK_ONLY_REQUIRED_FIELDS = true;

const csFieldVisible = (field) => {
	return window.getComputedStyle(field).display !== 'none';
};

const checkCollapsibleSectionComplete = (sectionBody) => {
	const toCheck = sectionBody.querySelectorAll('.-cs-field-check');
	const isComplete = sectionBody.querySelectorAll('.-cs-field-completed');
	const sectionComplete = ( Array.from(toCheck).filter(csFieldVisible).length === Array.from(isComplete).filter(csFieldVisible).length );
	document.getElementById( sectionBody.getAttribute('aria-labelledby') ).classList.toggle('-cs-completed', sectionComplete);
};

const toggleCollapsibleSectionFieldCompleted = (input, completed) => {
	input.closest('.gfield').classList.toggle('-cs-field-completed', completed);
	checkCollapsibleSectionComplete( input.closest('.collapsible-sections-collapsible-body') );
};

gform.addAction('gf_collapsible_sections_setup', (form_id, current_page, formDomId) => {
	
	const csFormWrap = document.querySelector(`#gform_wrapper_${formDomId}`);
	const csFieldsSelector = CS_CHECK_ONLY_REQUIRED_FIELDS ? '.gfield.gfield_contains_required' : '.gfield';
	csFormWrap.querySelectorAll(`.collapsible-sections-collapsible-body ${csFieldsSelector}:not(.gfield--type-hidden):not(.gfield--type-html):not(.gfield--type-section)`).forEach(field => {
		field.classList.add('-cs-field-check');
	});

	// text based inputs
	csFormWrap.querySelectorAll(`.-cs-field-check textarea, .-cs-field-check input:not([type="checkbox"]):not([type="radio"]:not([type="hidden"])`).forEach(input => {
		['change', 'keyup', 'blur'].forEach(eventName => {
			input.addEventListener(eventName, (e) => {
				const fieldCompleted = ( e.currentTarget.value !== '' );
				toggleCollapsibleSectionFieldCompleted( e.currentTarget, fieldCompleted );
			});
			input.dispatchEvent(new Event(eventName));
		});
	});

	// radio / checkbox based inputs
	csFormWrap.querySelectorAll(`.-cs-field-check input[type="radio"], .-cs-field-check input[type="checkbox"]`).forEach(input => {
		input.addEventListener('change', (e) => {
			const fieldCompleted = ( e.currentTarget.checked || e.currentTarget.closest('.ginput_container').querySelectorAll('input:checked').length );
			toggleCollapsibleSectionFieldCompleted( e.currentTarget, fieldCompleted );
		});
		input.dispatchEvent(new Event('change'));
	});
	
	// selects
	csFormWrap.querySelectorAll(`.-cs-field-check select`).forEach(select => {
		select.addEventListener('change', (e) => {
			const fieldCompleted = ( e.currentTarget.value !== '' );
			toggleCollapsibleSectionFieldCompleted( e.currentTarget, fieldCompleted );
		});
		select.dispatchEvent(new Event('change'));
	});
	
	// signature field input
	csFormWrap.querySelectorAll(`.-cs-field-check.gfield--type-signature input[name$="_data"]`).forEach(input => {
		input.addEventListener('change', (e) => {
			const fieldCompleted = ( e.currentTarget.value !== '' );
			toggleCollapsibleSectionFieldCompleted( e.currentTarget, fieldCompleted );
		});
		const observer = new MutationObserver(() => {
			input.dispatchEvent(new Event('change'));
		});
		observer.observe(input, {
			attributes: true,
			attributeFilter: ['value']
		});
		input.dispatchEvent(new Event('change'));
	});

});

jQuery(document).bind('gform_post_conditional_logic', (e, formId, fields, isInit) => {
	if ( !fields || !fields.length ) {
		return;
	}
	fields.forEach(fieldId => {
		const field = document.getElementById(`field_${formId}_${fieldId}`);
		if (!field || !field.classList.contains('-cs-field-check')) {
			return;
		}
		if ( field.classList.contains('gfield--type-signature') ) {
			field.querySelector('input[name$="_data"]').dispatchEvent(new Event('change'));
		}
		else {
			field.querySelector('textarea, input:not([type="hidden"]), select').dispatchEvent(new Event('change'));
		}		
	});
});
CSS design example #1

Left aligned checkmark

This CSS design example positions the complete check mark inline to the left of the section title. Makes for an easy and clean way to tell what a user has completed. Updated the colours below to customise it even further. Fill out some details in the demo below to see it in action.

.collapsible-sections-field.-cs-completed:not(.collapsible-sections-section-error):before {
    content: "✓";
    width: 20px;
    height: 20px;
    overflow: hidden;
    position: absolute;
	left: 20px;
    top: 50%;
    background-color: #2cc9b6;
    color: white;
    border-radius: 100px;
    line-height: 20px;
    font-size: 16px;
    text-align: center;
    transform: translateY(-50%);
    padding: 16px;
    display: flex;
    justify-content: center;
    align-items: center;
}
[class*=cs-theme--] .gsection.collapsible-sections-field.-cs-completed:not(.collapsible-sections-section-error) + .collapsible-sections-collapsible-body {
    --cs-border-color: #00b295;
	--cs-background-color: #e1fdf9;
}
[class*=cs-theme--] .gsection.collapsible-sections-field.-cs-completed:not(.collapsible-sections-section-error) {
    --cs-background-color: #e1fdf9;
    --cs-border-color: #00b295;
	padding-left: 70px !important;
}
CSS design example #2

Sections with images

This CSS example replaces the collapsible section image with the checkmark once the section has been completed.

.collapsible-sections-field.-cs-completed:not(.collapsible-sections-section-error):before {
    content: "✓";
    overflow: hidden;
    position: absolute;
    right: 60px;
    top: 50%;
    background-color: #2CC9B7;
    color: white;
    border-radius: var(--cs-image-radius);
    line-height: 20px;
    font-size: 16px;
    text-align: center;
    transform: translateY(-50%);
    padding: 16px;
    display: flex;
    justify-content: center;
    align-items: center;
    background-image: unset;
}
[class*=cs-theme--] .gsection.collapsible-sections-field.-cs-completed:not(.collapsible-sections-section-error) + .collapsible-sections-collapsible-body {
    --cs-border-color: #00b295;
}
[class*=cs-theme--] .gsection.collapsible-sections-field.-cs-completed:not(.collapsible-sections-section-error) {
    --cs-border-color: #00b295;
}

Group your fields.

Make your long forms easier to navigate by grouping them into collapsible sections and increase your form conversion. Easily group your Gravity Forms fields into accordion-style sections.

Buy Collapsible Sections

Give it a go!

With just a few lines of JavaScript, you can now give users a clearer sense of progress when filling out multi-section Gravity Forms. By visually marking collapsible sections as “complete” once all visible fields are filled, you’re improving the overall user experience, without needing complex validation logic. It’s a simple enhancement that brings a big UX win to your forms.

Tried it out? Show us your creative uses of section completion tracking! Share your examples or ideas with us on X, tag us @JetSloth_ and use #GravityForms to join the conversation. We’d love to see how you’re improving your forms!