Multi-Step Form
JSThis component requires JavaScript.
A multi-step form guides users through a long form by breaking it into smaller, sequential steps.
A multi-step form is designed for complex forms – such as applications, registrations or information requests – that require multiple inputs. By dividing inputs into manageable steps, users are able to focus on one task at a time, making long forms feel more approachable and easier to complete. Clear step labels and progress indicators help users understand where they are in the process and what comes next.
Example
Indoor space request
<div class="bux-multi-form" id="form-15644668">
<div class="bux-multi-form__layout">
<div class="bux-multi-form__form-container">
<div class="bux-multi-form__header">
<h2 class="bux-multi-form__title">Indoor space request</h2>
<div class="bux-progress-bar" aria-label="Progress" role="group">
<div class="bux-progress-bar__track">
<div class="bux-progress-bar__fill"></div>
</div>
<div class="bux-progress-bar__steps-container">
<div class="bux-progress-bar__step bux-progress-bar__step--current">
<span class="bux-progress-bar__icon">1</span>
</div>
<div class="bux-progress-bar__step bux-progress-bar__step--current">
<span class="bux-progress-bar__icon">2</span>
</div>
<div class="bux-progress-bar__step bux-progress-bar__step--current">
<span class="bux-progress-bar__icon">3</span>
</div>
<div class="bux-progress-bar__success">
<span class="bux-progress-bar__success-icon"></span>
</div>
</div>
</div>
</div>
<form class="bux-multi-form__form">
<div class="bux-multi-form__form-step is-active">
<h3 class="bux-multi-form__form-step-title-container">
<span class="bux-multi-form__form-step-title">Contact info</span>
<span class="bux-multi-form__step-counter">(Step 1 of 3)</span>
</h3>
<div class="bux-multi-form__form-field">
<div class="bux-text-field">
<label
class="bux-text-field__label"
for="bux-text-field__text-field-814372252"
>
First Name
<span class="bux-text-field__required">(required)</span>
</label>
<input
id="bux-text-field__text-field-814372252"
class="bux-text-field__input"
name="bux-text-field__text-field-814372252"
placeholder="Placeholder Text"
required
/>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-text-field">
<label
class="bux-text-field__label"
for="bux-text-field__text-field-1674032659"
>
Last Name
<span class="bux-text-field__required">(required)</span>
</label>
<input
id="bux-text-field__text-field-1674032659"
class="bux-text-field__input"
name="bux-text-field__text-field-1674032659"
placeholder="Placeholder Text"
required
/>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-text-field">
<label
class="bux-text-field__label"
for="bux-text-field__text-field-689660342"
>
Title
</label>
<input
id="bux-text-field__text-field-689660342"
class="bux-text-field__input"
name="bux-text-field__text-field-689660342"
placeholder="Placeholder Text"
/>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-text-field">
<label
class="bux-text-field__label"
for="bux-text-field__text-field-993073379"
>
Company
<span class="bux-text-field__required">(required)</span>
</label>
<input
id="bux-text-field__text-field-993073379"
class="bux-text-field__input"
name="bux-text-field__text-field-993073379"
placeholder="Placeholder Text"
required
/>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-text-field">
<label
class="bux-text-field__label"
for="bux-text-field__text-field-913312270"
>
Email
<span class="bux-text-field__required">(required)</span>
</label>
<input
id="bux-text-field__text-field-913312270"
class="bux-text-field__input"
name="bux-text-field__text-field-913312270"
placeholder="Placeholder Text"
required
/>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-text-field">
<label
class="bux-text-field__label"
for="bux-text-field__text-field-694895584"
>
Phone
<span class="bux-text-field__required">(required)</span>
</label>
<span
class="bux-text-field__helper-text"
id="bux-text-field__helper-text-694895584"
>
Include area code
</span>
<input
id="bux-text-field__text-field-694895584"
class="bux-text-field__input"
name="bux-text-field__text-field-694895584"
aria-describedby="bux-text-field__helper-text-694895584"
placeholder="555-555-5555"
required
/>
</div>
</div>
</div>
<div class="bux-multi-form__form-step">
<h3 class="bux-multi-form__form-step-title-container">
<span class="bux-multi-form__form-step-title">Event basics</span>
<span class="bux-multi-form__step-counter">(Step 2 of 3)</span>
</h3>
<div class="bux-multi-form__form-field">
<div class="bux-text-field">
<label
class="bux-text-field__label"
for="bux-text-field__text-field-688007023"
>
Event Name
</label>
<input
id="bux-text-field__text-field-688007023"
class="bux-text-field__input"
name="bux-text-field__text-field-688007023"
placeholder="Placeholder Text"
/>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-selection-dropdown">
<label
class="bux-selection-dropdown__label"
for="bux-selection-dropdown__selection-dropdown-1982471985"
>
Choose One
</label>
<div class="bux-selection-dropdown__input">
<select
id="bux-selection-dropdown__selection-dropdown-1982471985"
name="selection-dropdown-event-type"
>
<option>Choose One</option>
<option value="Symposium">Symposium</option>
<option value="Lecture">Lecture</option>
<option value="Holiday">Holiday</option>
</select>
</div>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-text-field">
<label
class="bux-text-field__label"
for="bux-text-field__text-field-492749420"
>
Event Start Date
</label>
<input
id="bux-text-field__text-field-492749420"
class="bux-text-field__input"
name="bux-text-field__text-field-492749420"
placeholder="Placeholder Text"
/>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-text-field">
<label
class="bux-text-field__label"
for="bux-text-field__text-field-782541963"
>
Event End Date
</label>
<input
id="bux-text-field__text-field-782541963"
class="bux-text-field__input"
name="bux-text-field__text-field-782541963"
placeholder="Placeholder Text"
/>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-radio">
<fieldset
id="bux-radio__radio-257919609"
class="bux-radio__fieldset"
>
<legend class="bux-radio__legend">
Is your date flexible?
</legend>
<div class="bux-radio__input-spacer">
<div class="bux-radio__option">
<input
type="radio"
id="bux-radio__option-361223528"
name="radio-button-flexible"
/>
<label for="bux-radio__option-361223528">Yes</label>
</div>
<div class="bux-radio__option">
<input
type="radio"
id="bux-radio__option-1762978023"
name="radio-button-flexible"
/>
<label for="bux-radio__option-1762978023">No</label>
</div>
</div>
</fieldset>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-text-field">
<label
class="bux-text-field__label"
for="bux-text-field__text-field-1974122514"
>
Timeframe of Event
</label>
<input
id="bux-text-field__text-field-1974122514"
class="bux-text-field__input"
name="bux-text-field__text-field-1974122514"
placeholder="Placeholder Text"
/>
</div>
</div>
</div>
<div class="bux-multi-form__form-step">
<h3 class="bux-multi-form__form-step-title-container">
<span class="bux-multi-form__form-step-title">Event details</span>
<span class="bux-multi-form__step-counter">(Step 3 of 3)</span>
</h3>
<div class="bux-multi-form__form-field">
<div class="bux-text-field">
<label
class="bux-text-field__label"
for="bux-text-field__text-field-459941135"
>
Total Number of Guests
</label>
<input
id="bux-text-field__text-field-459941135"
class="bux-text-field__input"
name="bux-text-field__text-field-459941135"
placeholder="Placeholder Text"
/>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-selection-dropdown">
<label
class="bux-selection-dropdown__label"
for="bux-selection-dropdown__selection-dropdown-1384034425"
>
Choose One
</label>
<div class="bux-selection-dropdown__input">
<select
id="bux-selection-dropdown__selection-dropdown-1384034425"
name="selection-dropdown-room-setup"
>
<option>Choose One</option>
<option value="Option 1">Option 1</option>
<option value="Option 2">Option 2</option>
<option value="Option 3">Option 3</option>
</select>
</div>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-radio">
<fieldset
id="bux-radio__radio-1710120025"
class="bux-radio__fieldset"
>
<legend class="bux-radio__legend">
Are breakout rooms required?
</legend>
<div class="bux-radio__input-spacer">
<div class="bux-radio__option">
<input
type="radio"
id="bux-radio__option-1646024619"
name="radio-button-breakout"
/>
<label for="bux-radio__option-1646024619">Yes</label>
</div>
<div class="bux-radio__option">
<input
type="radio"
id="bux-radio__option-1824517078"
name="radio-button-breakout"
/>
<label for="bux-radio__option-1824517078">No</label>
</div>
</div>
</fieldset>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-radio">
<fieldset
id="bux-radio__radio-165472270"
class="bux-radio__fieldset"
>
<legend class="bux-radio__legend">Is catering required?</legend>
<div class="bux-radio__input-spacer">
<div class="bux-radio__option">
<input
type="radio"
id="bux-radio__option-1596548724"
name="radio-button-catering"
/>
<label for="bux-radio__option-1596548724">Yes</label>
</div>
<div class="bux-radio__option">
<input
type="radio"
id="bux-radio__option-1192675363"
name="radio-button-catering"
/>
<label for="bux-radio__option-1192675363">No</label>
</div>
</div>
</fieldset>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-radio">
<fieldset
id="bux-radio__radio-195614503"
class="bux-radio__fieldset"
>
<legend class="bux-radio__legend">
Will your group require overnight rooms?
</legend>
<div class="bux-radio__input-spacer">
<div class="bux-radio__option">
<input
type="radio"
id="bux-radio__option-351841712"
name="radio-button-overnight"
/>
<label for="bux-radio__option-351841712">Yes</label>
</div>
<div class="bux-radio__option">
<input
type="radio"
id="bux-radio__option-1176006578"
name="radio-button-overnight"
/>
<label for="bux-radio__option-1176006578">No</label>
</div>
</div>
</fieldset>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-radio">
<fieldset
id="bux-radio__radio-1429868559"
class="bux-radio__fieldset"
>
<legend class="bux-radio__legend">
Do you have a preferred venue?
</legend>
<div class="bux-radio__input-spacer">
<div class="bux-radio__option">
<input
type="radio"
id="bux-radio__option-1464630152"
name="radio-button-venue"
/>
<label for="bux-radio__option-1464630152">Yes</label>
</div>
<div class="bux-radio__option">
<input
type="radio"
id="bux-radio__option-824383846"
name="radio-button-venue"
/>
<label for="bux-radio__option-824383846">No</label>
</div>
</div>
</fieldset>
</div>
</div>
<div class="bux-multi-form__form-field">
<div class="bux-text-area">
<label
class="bux-text-area__label"
for="bux-text-area__text-area-390076898"
>
Additional Comments
</label>
<textarea
id="bux-text-area__text-area-390076898"
class="bux-text-area__text-area"
name="bux-text-area__text-area-390076898"
placeholder="Placeholder Text"
></textarea>
</div>
</div>
</div>
<div class="bux-multi-form__confirmation">
<div class="bux-multi-form__confirmation-content">
<h3 class="bux-multi-form__form-title-container">Form complete</h3>
<div>Thank you for submitting.</div>
</div>
</div>
<div class="bux-multi-form__button-container">
<div class="bux-multi-form__back-button">
<button class="bux-button bux-button--alt">Back</button>
</div>
<div class="bux-multi-form__next-button">
<button class="bux-button">Next</button>
</div>
</div>
</form>
</div>
</div>
</div>
{#
Buckeye UX - version 1.5.0
Copyright (C) 2026 The Ohio State University
#}
{#
Multi Step Form
Available Variables:
- form_title: Title of the multi-step form.
- steps: An array of steps. Each step contains an array of form fields.
- modifier: Optional. Modifier for the multi-step form: null, featured.
- featured_card_type: Optional. Featured card type if using the featured modifier: image, panel, text.
- featured_card_data: Optional. Featured card data: [image_url, image_alt_ext] or [panel_title, panel_text]
- featured_card_position: Optional. Position of the featured card: left, right.
This DocBlock is auto-generated and any changes could be overwritten.
Use the component's corresponding *.config.ts to make changes to this file.
Last Updated: 04-01-2026 15:04:38
#}
{% if featured_card_type %}
{% set featured_card_position = featured_card_position|default('left') %}
{% endif %}
{% set featured_card %}
{% if featured_card_type %}
<div class="bux-multi-form__featured-card">
{% if featured_card_type == 'image' %}
{% include '@bux/image/image.twig' with featured_card_data %}
{% elseif featured_card_type == 'panel' %}
{% include '@bux/panel/panel.twig' with featured_card_data %}
{% elseif featured_card_type == 'text' %}
<div class="bux-multi-form__text">
{{ featured_card_data.text|raw }}
</div>
{% endif %}
</div>
{% endif %}
{% endset %}
<div class="bux-multi-form" id="form-{{ random() }}">
<div class="bux-multi-form__layout">
{% if featured_card_position == 'left' %}{{ featured_card }}{% endif %}
<div
class="bux-multi-form__form-container{{ featured_card_type ? ' bux-multi-form__form-container--featured' : '' }}{{
modifier
? ' bux-multi-form__form-container--' ~ modifier
: ''
}}"
>
<div class="bux-multi-form__header">
<h2 class="bux-multi-form__title">{{ form_title }}</h2>
{% include '@bux/forms/_subcomponents/progress-bar/progress-bar.twig' %}
</div>
<form class="bux-multi-form__form">
{% for step in steps %}
<div class="bux-multi-form__form-step{{ loop.index == 1 ? ' is-active' : '' }}">
<h3 class="bux-multi-form__form-step-title-container">
<span class="bux-multi-form__form-step-title">{{ step.name }}</span>
<span class="bux-multi-form__step-counter">(Step {{ loop.index }} of {{ steps|length }})</span>
</h3>
{% for question in step.questions %}
<div class="bux-multi-form__form-field">
{% set form_field = '@bux/forms/' ~ (question.field|trim) ~ '/' ~ (question.field|trim) ~ '.twig' %}
{% include form_field with question.context ?? {} %}
</div>
{% endfor %}
</div>
{% endfor %}
<div class="bux-multi-form__confirmation">
<div class="bux-multi-form__confirmation-content">
<h3 class="bux-multi-form__form-title-container">{{ confirmation.subtitle|default('Form complete') }}</h3>
<div>
{{ confirmation.text|default('Thank you for submitting.') }}
</div>
</div>
</div>
<div class="bux-multi-form__button-container">
<div class="bux-multi-form__back-button">
{% include '@bux/button/button.twig' with {
button_text: 'Back',
modifier: 'alt'
} %}
</div>
<div class="bux-multi-form__next-button">
{% include '@bux/button/button.twig' with {
button_text: 'Next'
} %}
</div>
</div>
</form>
</div>
{% if featured_card_position == 'right' %}{{ featured_card }}{% endif %}
</div>
</div>
Usage
Dos
- Use the step indicator when the user is working through a form or process that will span several different pages that can be organized into three or more high-level steps or chapters.
- Group related fields into logical steps so each step has a clear purpose.
- When writing step titles, be concise. Limit to a few words.
- Display step and total with the step title, such as "Step 1 of 3" to reinforce the number of steps and help users understand where they are in the process.
Don’ts
- Don’t use a multi-step form for short forms without logical groupings or sections. If a form or process has fewer than three sections, consider standard Form components.
- Don't hide critical information, such as requirements or deadlines, until late in the process.
Implementation notes
Submission Handling
- This component intercepts the standard form submission and dispatches a custom JavaScript event (
bux-form:submit) on the main container. If this event isn't captured, it defaults to simulating a 1-second loading state before showing the success screen. - To actually handle submissions, you must listen for the
bux-form:submitevent, cancel the default behaviorevent.preventDefault()and trigger your callback.
/**
* Simple Custom Submission Script Example
* - Intercept the submission default and POST the results to your endpoint
*/
const formContainer = document.querySelector('#your-multi-step-form-id');
formContainer.addEventListener('bux-form:submit', (event) => {
event.preventDefault(); // Cancels the default behavior
// Access event details provided by the JavaScript
const formData = event.detail.formData;
const { success, fail } = event.detail
fetch('/your-endpoint', {
method: 'POST',
body: formData
})
.then(response => {
if (response.ok) {
// Transitions the form to the confirmation page
success();
} else {
// Alert user of problem without proceeding to the confirmation page
fail('Something went wrong. Please try again.');
}
})
.catch(error => {
// Alert user of problem without proceeding to the confirmation page
fail(error.message);
});
}
Defining Steps
- Each step should be a wrapper
divwith the classbux-multi-form__form-step. The script will count the number of elements with this class. - The first step in your form should include the
is-activeclass on initial load - Form Elements for a particular step should be nested within the step
divwrappers. Refer to form element documentation for implementation notes per form element.
Important Things to Keep in Mind
- All Multi-Step Forms are initialized via the top-level container's ID. If that doesn't exist, the form will not initialize.
- If any of the following elements are not available on initialization, the JavaScript will fail with a
TypeError: form, next/back button, progress bar wrapper, container, confirmation wrapper- If the form isn't initializing check your console and see if this error is popping up