Creating a multistep form involves structuring your HTML for multiple steps, using CSS for styling, and JavaScript to handle the navigation between steps. Here’s a basic example to get you started:
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Multistep Form</title>
<link rel="stylesheet" href="style.css" />
<script src="script.js" defer></script>
</head>
<body>
<form class="form-wizard">
<!-- .completed -->
<div class="completed" hidden>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"
/>
</svg>
<h3>Registration Successful!</h3>
<p>Your account has been created.</p>
</div>
<!-- /.completed -->
<h1>Registration</h1>
<!-- .progress-container -->
<div class="progress-container">
<div class="progress"></div>
<ol>
<li class="current">Personal Info</li>
<li>Contact Info</li>
<li>Account Info</li>
<li>About</li>
</ol>
</div>
<!-- /.progress-container -->
<!-- .steps-container -->
<div class="steps-container">
<div class="step">
<h3>Personal Information</h3>
<div class="form-control">
<label for="first-name">First Name</label>
<input type="text" id="first-name" name="first-name" required />
</div>
<div class="form-control">
<label for="last-name">Last Name</label>
<input type="text" id="last-name" name="last-name" required />
</div>
</div>
<div class="step">
<h3>Contact Information</h3>
<div class="form-control">
<label for="email">Email</label>
<input type="email" id="email" name="email" required />
</div>
<div class="form-control">
<label for="phone">Phone</label>
<input type="tel" id="phone" name="phone" required />
</div>
</div>
<div class="step">
<h3>Account Information</h3>
<div class="form-control">
<label for="username">Username</label>
<input type="text" id="username" name="username" required />
</div>
<div class="form-control">
<label for="password">Password</label>
<input type="password" id="password" name="password" required />
</div>
<div class="form-control">
<label for="confirm-password">Confirm Password</label>
<input
type="password"
id="confirm-password"
name="confirm-password"
required
/>
</div>
</div>
<div class="step">
<h3>About</h3>
<div class="form-control">
<label for="bio">Bio</label>
<textarea name="bio" id="bio" rows="4" required></textarea>
</div>
</div>
</div>
<!-- /.steps-container -->
<!-- .controls -->
<div class="controls">
<button type="button" class="prev-btn">Prev</button>
<button type="button" class="next-btn">Next</button>
<button type="submit" class="submit-btn">Submit</button>
</div>
<!-- /.controls -->
</form>
</body>
</html>
CSS (styles.css)
@import url("https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600&display=swap");
* {
font-family: "Outfit", sans-serif;
padding: 0;
margin: 0;
box-sizing: border-box;
}
:root {
--main-color: #c41e67;
--dark-color: #a71555;
--step-color: #ced7e0;
--step-size: 32px;
--steps: 4;
--progress-width: calc((var(--steps) - 1) / var(--steps) * 100%);
}
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-color: lavender;
color: #333;
overflow: hidden;
}
h1 {
text-align: center;
margin-bottom: 16px;
}
h3 {
margin-bottom: 16px;
}
label {
display: inline-block;
margin-bottom: 4px;
}
input,
textarea {
outline-color: var(--main-color);
border: 1px solid lightgray;
padding: 8px 16px;
border-radius: 4px;
width: 100%;
font-size: 16px;
}
textarea {
resize: none;
}
button {
cursor: pointer;
border: none;
border-radius: 16px;
padding: 8px 16px;
background-color: var(--main-color);
color: #fff;
font-size: 14px;
transition: 0.3s;
}
button:active,
button:hover {
background-color: var(--dark-color);
}
button:disabled {
opacity: 0.8;
}
button:focus {
outline-color: #333;
}
button[type="submit"] {
background-color: #333;
}
button[type="submit"]:hover,
button[type="submit"]:active {
background-color: #444;
}
/* form styles */
.form-wizard {
background-color: #fff;
padding: 32px;
border-radius: 8px;
width: min(600px, 80%);
box-shadow: 0 4px 16px rgba(167, 21, 84, 0.1);
}
.progress-container {
position: relative;
}
.progress-container::before {
content: "";
height: 4px;
width: var(--progress-width);
background-color: var(--step-color);
position: absolute;
top: calc(var(--step-size) / 2);
left: 50%;
translate: -50% -50%;
}
.progress-container .progress {
height: 4px;
width: var(--progress-width);
background-color: var(--main-color);
position: absolute;
top: calc(var(--step-size) / 2);
left: 50%;
translate: -50% -50%;
z-index: 2;
transform: scaleX(0);
transform-origin: left;
transition: 0.3s;
}
.progress-container ol {
list-style-type: none;
display: flex;
align-items: flex-start;
justify-content: space-between;
counter-reset: step-number;
position: relative;
z-index: 3;
}
.progress-container li {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
color: var(--step-color);
transition: 0.3s linear 0.3s;
text-align: center;
}
.progress-container li::before {
counter-increment: step-number;
content: counter(step-number);
background-color: var(--step-color);
width: var(--step-size);
height: var(--step-size);
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
color: #fff;
transition: 0.3s linear 0.3s;
}
.progress-container li:where(.done, .current) {
color: #333;
font-weight: 500;
}
.progress-container li.done::before {
background-color: var(--main-color);
}
.progress-container li.current::before {
background-color: var(--main-color);
box-shadow: 0 0 0 3px rgba(167, 21, 84, 0.25);
}
.steps-container {
display: flex;
overflow: hidden;
}
.step {
flex: 1 0 100%;
padding: 24px 8px;
opacity: 0;
transition: opacity 0.3s;
height: fit-content;
display: grid;
gap: 8px;
}
.step.current {
opacity: 1;
}
.controls {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
margin-top: 16px;
padding-inline: 8px;
}
.controls button {
flex: 1;
}
.completed {
text-align: center;
}
.completed h3 {
margin-bottom: 8px;
}
.completed svg {
width: 100px;
height: 100px;
stroke: yellowgreen;
}
.completed:not([hidden]) ~ * {
display: none;
}
JavaScript (script.js)
document.addEventListener("DOMContentLoaded", () => {
const form = document.querySelector(".form-wizard");
const progress = form.querySelector(".progress");
const stepsContainer = form.querySelector(".steps-container");
const steps = form.querySelectorAll(".step");
const stepIndicators = form.querySelectorAll(".progress-container li");
const prevButton = form.querySelector(".prev-btn");
const nextButton = form.querySelector(".next-btn");
const submitButton = form.querySelector(".submit-btn");
document.documentElement.style.setProperty("--steps", stepIndicators.length);
let currentStep = 0;
const updateProgress = () => {
let width = currentStep / (steps.length - 1);
progress.style.transform = `scaleX(${width})`;
stepsContainer.style.height = steps[currentStep].offsetHeight + "px";
stepIndicators.forEach((indicator, index) => {
indicator.classList.toggle("current", currentStep === index);
indicator.classList.toggle("done", currentStep > index);
});
steps.forEach((step, index) => {
step.style.transform = `translateX(-${currentStep * 100}%)`;
step.classList.toggle("current", currentStep === index);
});
updateButtons();
};
const updateButtons = () => {
prevButton.hidden = currentStep === 0;
nextButton.hidden = currentStep >= steps.length - 1;
submitButton.hidden = !nextButton.hidden;
};
const isValidStep = () => {
const fields = steps[currentStep].querySelectorAll("input, textarea");
return [...fields].every((field) => field.reportValidity());
};
//* event listeners
const inputs = form.querySelectorAll("input, textarea");
inputs.forEach((input) =>
input.addEventListener("focus", (e) => {
const focusedElement = e.target;
// get the step where the focused element belongs
const focusedStep = [...steps].findIndex((step) =>
step.contains(focusedElement)
);
if (focusedStep !== -1 && focusedStep !== currentStep) {
if (!isValidStep()) return;
currentStep = focusedStep;
updateProgress();
}
stepsContainer.scrollTop = 0;
stepsContainer.scrollLeft = 0;
})
);
form.addEventListener("submit", (e) => {
e.preventDefault(); // prevent form submission
if (!form.checkValidity()) return;
const formData = new FormData(form);
// send the data somewhere
console.log(Object.fromEntries(formData));
submitButton.disabled = true;
submitButton.textContent = "Submitting...";
// mimic a server request
setTimeout(() => {
form.querySelector(".completed").hidden = false;
}, 3000);
});
prevButton.addEventListener("click", (e) => {
e.preventDefault(); // prevent form submission
if (currentStep > 0) {
currentStep--;
updateProgress();
}
});
nextButton.addEventListener("click", (e) => {
e.preventDefault(); // prevent form submission
if (!isValidStep()) return;
if (currentStep < steps.length - 1) {
currentStep++;
updateProgress();
}
});
updateProgress();
});
Explanation
- HTML:
- The form is divided into multiple
divelements, each representing a step. - Each step contains form fields and navigation buttons (
NextandPrevious). - Only the first step is initially visible (class
active).
- The form is divided into multiple
- CSS:
- Basic styling for the form and buttons.
- Only the
divwith the classactiveis displayed, others are hidden (display: none).
- JavaScript:
- Event listeners for the
NextandPreviousbuttons change the active step. - The
changeStepfunction hides the current step and shows the next or previous step based on the button clicked.
- Event listeners for the
With this structure, you can easily add more steps or customize the form as needed.


+91 7905834592
Enquiry Now
piyushmnm@gmail.com
piyush.gupta384
Reviews
There are no reviews yet. Be the first one to write one.