Multi-Step Forms With Vanilla JavaScript and CSS

by appel

HTML

<script src="//fonts.googleapis.com/css2?family=Comfortaa:wght@300..700&amp;display=swap"></script>
<h1>Multi-Step Forms With Vanilla JavaScript and CSS</h1>
<form id="myForm">
  <section class="group-one" id="one">
    <div class="form-group">
      <div class="form-control">
        <label for="name">
          Name
          <span style="color: red">*</span>
        </label>
        <input
          type="text"
          id="name"
          name="name"
          placeholder="Enter your name"
          aria-required="true"
        />
        <span id="name-error" class="error-message" role="alert"></span>
      </div>
      <div class="form-control">
        <label for="idNum">
          ID number
          <span style="color: red">*</span>
        </label>
        <input
          type="number"
          id="idNum"
          name="idNum"
          placeholder="Enter your ID number"
          aria-required="true"
        />
        <span id="id-error" class="error-message" role="alert"></span>
      </div>
    </div>
    <div class="form-group">
      <div class="form-control">
        <label for="email">
          Email
          <span style="color: red">*</span>
        </label>
        <input
          type="email"
          id="email"
          name="email"
          placeholder="Enter your email"
          aria-required="true"
        />
        <span id="email-error" class="error-message" role="alert"></span>
      </div>
      <div class="form-control">
        <label for="birthdate">
          Date of Birth
          <span style="color: red">*</span>
        </label>
        <input
          type="date"
          id="birthdate"
          name="birthdate"
          max="2006-10-01"
          min="1924-01-01"
          aria-required="true"
        />
        <span id="bd-error" class="error-message" role="alert"></span>
        <span id="error"></span>
      </div>
    </div>
  </section>
  <section class="group-two" id="two">
    <div...

CSS

:root {
  --primary-color: #8c852a;
  --secondary-color: #858034;
  --form-max-width: 600px;
}

body {
  font-family: "Comfortaa", sans-serif;
  line-height: 1.4;
  margin: 0 auto;
  padding: 20px;
  background-color: #f4f4f4;
  max-width: 600px;
}

.lang-select {
  width: fit-content;
  margin-left: auto;
}

h1 {
  text-align: center;
}

p,
p a {
  font-size: 0.85rem;
  color: #999;
}

form {
  background: #fff;
  padding: 40px;
  border-radius: 5px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
}

.form-group {
  display: flex;
  gap: 7%;
}

.form-group > div {
  width: 100%;
}

input:not([type="checkbox"]),
select,
textarea {
  width: 100%;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.form-control {
  margin-bottom: 15px;
}

input:focus,
select:focus,
textarea:focus {
  outline: 0.5px solid var(--primary-color);
}

input.error,
select.error,
textarea.error {
  outline: 0.5px solid red;
}

button {
  display: block;
  width: 100%;
  padding: 10px;
  color: white;
  background-color: var(--primary-color);
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
}

button:hover {
  background-color: var(--secondary-color);
}

span#error,
span[id$="-error"] {
  font-size: x-small;
  color: red;
  margin-top: 2px;
}

.group-two,
.group-three {
  display: none;
}

.arrows {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 10px;
  color: var(--primary-color);
  font-size: 18px;
  font-weight: 900;
}

#navLeft,
#navRight {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
}

.nav-group {
  width: fit-content;
}

.summary-section {
  display: flex;
  align-items: center;
  gap: 10px;
}

.summary-section p:first-child {
  width: 30%;
  flex-shrink: 0;
  border-right: 1px solid var(--secondary-color);
}

.summary-section p:nth-child(2) {
  width: 45%;
  flex-shrink: 0;
  padding-left: 10px;
}

.edit-btn {
  width: 25%;
 ...

JavaScript

const stepInfo = document.getElementById("stepInfo")
const navLeftGroup = document.getElementById("navLeft")
const navRightGroup = document.getElementById("navRight")

const nameInput = document.getElementById("name")
const idNumInput = document.getElementById("idNum")
const emailInput = document.getElementById("email")
const birthdateInput = document.getElementById("birthdate")
const documentInput = document.getElementById("document")
const departmentInput = document.getElementById("department")
const skillsInput = document.getElementById("skills")
const termsCheckbox = document.getElementById("terms")

const nameVal = document.getElementById("name-val")
const idVal = document.getElementById("id-val")
const emailVal = document.getElementById("email-val")
const bdVal = document.getElementById("bd-val")
const cvVal = document.getElementById("cv-val")
const deptVal = document.getElementById("dept-val")
const skillsVal = document.getElementById("skills-val")

const form = document.getElementById("myForm")
const formStepsID = ["one", "two", "three", "four"]
let currentFormStep = 0

const editButtons = {
  "name-edit": 0,
  "id-edit": 0,
  "email-edit": 0,
  "bd-edit": 0,
  "cv-edit": 1,
  "dept-edit": 1,
  "skills-edit": 2,
}

const updateSummaryValues = () => {
  nameVal.textContent = nameInput.value
  idVal.textContent = idNumInput.value
  emailVal.textContent = emailInput.value
  bdVal.textContent = birthdateInput.value
  const fileName = documentInput.files[0]?.name
  if (fileName) {
    const extension = fileName.split(".").pop()
    const baseName = fileName.split(".")[0]
    const truncatedName =
      baseName.length > 10 ? baseName.substring(0, 10) + "..." : baseName
    cvVal.textContent = `${truncatedName}.${extension}`
  } else {
    cvVal.textContent = "No file selected"
  }
  deptVal.textContent = departmentInput.value
  skillsVal.textContent = skillsInput.value || "No skills submitted"
}

const updateStepVisibility = () => {
 ...