Awesome Stepper Form with HTML/CSS/JavaScript
Tags: html, css, javascript, webdev
Published: 2019-10-28 17:29:21

Originally posted on [my blog](https://www.ibrahima-ndaw.com/blog/awesome-stepper-form/) <hr>

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](https://codepen.io/ibrahima92) : [Stepper Form](https://codepen.io/ibrahima92/full/bGGrVxq)

Let's get started!

## Markup

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

```html
    <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. 

```css
@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.

```css
.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.

```css
.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 will 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.

```css
.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. 

```css
@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. 

```javascript
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.

```javascript
// 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.

```javascript
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](https://drive.google.com/uc?id=1bOsvCxxQqubQtskaITnCNS1GKX66gpjM)


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

You can follow me on [Twitter](https://twitter.com/ibrahima92_) to get notified when a new article is published.

Thanks for reading!

| [TWITTER](https://twitter.com/ibrahima92_) | [BLOG](https://www.ibrahima-ndaw.com/) | [NEWSLETTER](https://ibrahima-ndaw.us5.list-manage.com/subscribe?u=8dedf5d07c7326802dd81a866&id=5d7bcd5b75) | [GITHUB](https://github.com/ibrahima92) | [LINKEDIN](https://www.linkedin.com/in/ibrahima-ndaw/) | [CODEPEN](https://codepen.io/ibrahima92) | [DEV](https://dev.to/ibrahima92) |
| -------------- | ------------------------------------------ | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------ | ---------------------------------------- | -------------------------------- |