Awesome Stepper Form with HTML, CSS, and JavaScript

cover

Subscribe to receive the free weekly article

This article has been updated on 2020-11-02

A stepper or multi-step form is a handy feature to have when dealing with long-forms. It enhances your user experience with a more user-friendly form format. In this tutorial, we will be creating a stepper form using HTML, CSS, and JavaScript.

You can check it live on Codepen : Stepper Form

Let's get started!

Markup

As you can see, the HTML file is relatively simple.

<main>
  <div class="stepper">
    <div class="step--1 step-active">Step 1</div>
    <div class="step--2">Step 2</div>
    <div class="step--3">Step 3</div>
    <div class="step--4">Finish</div>
  </div>
  <form class="form form-active">
    <div class="form--header-container">
      <h1 class="form--header-title">
        Personal Info
      </h1>

      <p class="form--header-text">
        Tell us more about you.
      </p>
    </div>
    <input type="text" placeholder="Name" />
    <input type="text" placeholder="Email" />
    <input type="text" placeholder="Password" />
    <button class="form__btn" id="btn-1">Next</button>
  </form>
  <form class="form">
    <div class="form--header-container">
      <h1 class="form--header-title">
        Company Info
      </h1>

      <p class="form--header-text">
        Tell us more about your company.
      </p>
    </div>

    <input type="text" placeholder="Company Name" />
    <input type="text" placeholder="Job title" />
    <input type="text" placeholder="Location" />
    <button class="form__btn" id="btn-2-prev">Previous</button>
    <button class="form__btn" id="btn-2-next">Next</button>
  </form>
  <form class="form">
    <div class="form--header-container">
      <h1 class="form--header-title">
        Social account
      </h1>

      <p class="form--header-text">
        Tell us more about your social account.
      </p>
    </div>
    <input type="text" placeholder="Linkedin" />
    <input type="text" placeholder="Twitter" />
    <input type="text" placeholder="Github" />
    <button class="form__btn" id="btn-3">Submit</button>
  </form>
  <div class="form--message"></div>
</main>

Besides the main tag, we also define a div that holds the stepper element. Then, we use three forms with different buttons id which will soon make the stepper effect with the help of JavaScript.

With this in place, we can now style the project with CSS.

Styling

Here, we begin with some resets and then set the font-family and background-color properties for the body tag.

@import url("https://fonts.googleapis.com/css?family=Nunito&display=swap");
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body {
  background: #f5f6f7;
  font-family: "Nunito", sans-serif;
}

main {
  height: 100vh;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  position: relative;
}

Next, we use the flex value on the main tag to center the element relative to the body tag.

.stepper {
  width: 20rem;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  top: 5%;
}

.step--1,
.step--2,
.step--3,
.step--4 {
  width: 5rem;
  padding: 0.5rem 0;
  background: #fff;
  color: #666;
  text-align: center;
}
.step--1,
.step--2,
.step--3 {
  border-right: 1px solid #666;
}

For the Stepper elements, we rely on CSS flexbox to align them horizontally and then use their class names to add the style.

.form {
  background: #fff;
  text-align: center;
  position: absolute;
  width: 25rem;
  box-shadow: 0.2rem 0.2rem 0.5rem rgba(51, 51, 51, 0.2);
  display: none;
  border-radius: 1rem;
  overflow: hidden;
}
.form--header-container {
  background: linear-gradient(to right, rgb(51, 51, 51), #919191);
  color: #fff;
  height: 6rem;
  padding: 1rem 0;
  margin-bottom: 2rem;
}

.form--header-title {
  font-size: 1.4rem;
}

.form--header-text {
  padding: 0.5rem 0;
}

input[type="text"] {
  padding: 0.8rem;
  margin: auto;
  margin-top: 0.5rem;
  width: 20rem;
  display: block;
  border-radius: 0.5rem;
  outline: none;
  border: 1px solid #bdbdbb;
}

.form__btn {
  background: #333;
  color: #fff;
  outline: none;
  border: none;
  padding: 0.5rem 0.7rem;
  width: 7rem;
  margin: 1rem auto;
  border-radius: 0.9rem;
  text-transform: uppercase;
  font-weight: 700;
  cursor: pointer;
}
.form--message-text {
  width: 25rem;
  background: #fff;
  color: #444;
  padding: 2rem 1rem;
  text-align: center;
  font-size: 1.4rem;
  box-shadow: 0.2rem 0.2rem 0.5rem rgba(51, 51, 51, 0.2);
  animation: fadeIn 0.8s;
  border-radius: 1rem;
}

In the beginning, we hide all three forms. Only the form that contains the class active class will be shown.

In the form--header-container class, we use linear-gradient to style the form header.

Next, in the form--message-text class, we add the animation property to have a fade-in effect when the form is submitted successfully.

.form-active {
  z-index: 1000;
  display: block;
}
.form-active-animate {
  animation: moveRight 1s;
}
.form-inactive {
  display: block;
  animation: moveLeft 1s;
}

.step-active {
  background: #666;
  color: #fff;
  border: 1px solid #666;
}

We use the form-active class to show the current form. And also the property z-index to put the form on top of other elements.

Next, we use the form-active-animate class to make a nice animation entrance from the left to the right. We also have the class name form-inactive that helps hide the previous form.

@keyframes moveRight {
  0% {
    transform: translateX(-27rem) scale(0.9);
    opacity: 0;
  }
  100% {
    transform: translateX(0rem) scale(1);
    opacity: 1;
  }
}

@keyframes moveLeft {
  0% {
    transform: translateX(0rem) scale(1);
    opacity: 1;
  }
  100% {
    transform: translateX(27rem) scale(0.9);
    opacity: 0;
  }
}

@keyframes fadeIn {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

As you can see here, we rely on keyframes to make the animation.

The first animation, moveRight will move the element from left to right using the property transform.

For the second animation, this is relatively the same process, except the element will move more on the right side.

The last animation, fadeIn, will start the fade-in effect when the element shows.

JavaScript

As you can see here, we listen to the click event and then use the gotoNextForm function to handle it.

const formBtn1 = document.querySelector("#btn-1")
const formBtnPrev2 = document.querySelector("#btn-2-prev")
const formBtnNext2 = document.querySelector("#btn-2-next")
const formBtn3 = document.querySelector("#btn-3")

To interact with the DOM, we need to select all form buttons using the querySelector method.

// Button listener of form 1
formBtn1.addEventListener("click", function(e) {
  gotoNextForm(formBtn1, formBtnNext2, 1, 2)
  e.preventDefault()
})

// Next button listener of form 2
formBtnNext2.addEventListener("click", function(e) {
  gotoNextForm(formBtnNext2, formBtn3, 2, 3)
  e.preventDefault()
})

// Previous button listener of form 2
formBtnPrev2.addEventListener("click", function(e) {
  gotoNextForm(formBtnNext2, formBtn1, 2, 1)
  e.preventDefault()
})

// Button listener of form 3
formBtn3.addEventListener("click", function(e) {
  document.querySelector(`.step--3`).classList.remove("step-active")
  document.querySelector(`.step--4`).classList.add("step-active")
  formBtn3.parentElement.style.display = "none"
  document.querySelector(".form--message").innerHTML = `
   <h1 class="form--message-text">Your account is successfully created </h1>
   `
  e.preventDefault()
})

Here, we start by passing in the form ids as parameters and then use the method preventDefault() on the event to prevent the page reload.

The listener formBtn3 is a bit different because we have to show a message to the user. That's why we use innerHTML to append the content.

const gotoNextForm = (prev, next, stepPrev, stepNext) => {
  // Get form through the button
  const prevForm = prev.parentElement
  const nextForm = next.parentElement
  const nextStep = document.querySelector(`.step--${stepNext}`)
  const prevStep = document.querySelector(`.step--${stepPrev}`)
  // Add active/inactive classes to both previous and next form
  nextForm.classList.add("form-active")
  nextForm.classList.add("form-active-animate")
  prevForm.classList.add("form-inactive")
  // Change the active step element
  prevStep.classList.remove("step-active")
  nextStep.classList.add("step-active")
  // Remove active/inactive classes to both previous an next form
  setTimeout(() => {
    prevForm.classList.remove("form-active")
    prevForm.classList.remove("form-inactive")
    nextForm.classList.remove("form-active-animate")
  }, 1000)
}

Here, we traverse the DOM using the parentElement property on both prevForm and nextForm variables to select the form element.

Next, we use the variables to select the form steps from the stepper element.

After that, we add the classes form-active and form-active-animate to the next form element to have a nice animation effect.

Next, we remove form-active, form-inactive and form-active-animate classes from the forms after 1 second using setTimeout().

stepper-form

Great! We are done building an Awesome Stepper Form with HTML, CSS, and JavaScript.

You can follow me on Twitter to get notified when a new article is published.

Thanks for reading!

#html#css#javascript

Support my work

Get articles in your inbox