ホームページ > ウェブフロントエンド > CSSチュートリアル > バニラJavaScriptとCSSでマルチステップフォームを作成する方法

バニラJavaScriptとCSSでマルチステップフォームを作成する方法

William Shakespeare
リリース: 2025-03-07 16:55:11
オリジナル
272 人が閲覧しました

How to Create Multi-Step Forms With Vanilla JavaScript and CSS

マルチステップフォームは、フォームが大きく、多くのコントロールがある場合に適しています。モバイルデバイス上の非常に長いフォームをスクロールしたい人はいません。画面ごとにコントロールをグループ化することにより、長く複雑なフォームに記入する経験を向上させることができます。

しかし、最後にマルチステップフォームを開発したのはいつですか?それはあなたにとっても楽しく聞こえますか?考えるべきことがたくさんあり、管理する必要がある非常に多くの感動的な作品があるので、フォームライブラリや、すべてを処理するフォームウィジェットに頼ることであなたを責めることはありません。

しかし、手作業でそれを行うことは、良い運動であり、基本を磨くための素晴らしい方法です。最初のマルチステップフォームをどのように作成したかを紹介します。それがどれほど親しみやすいかを見るだけでなく、私の仕事をさらに良くするために領域を見つけられることを願っています。

一緒に構造を通り抜けます。私たちの多くは、私たちの多くが最近の日に関係することができると思います。最初にベースラインHTML、CSS、およびJavaScriptを足場にし、次にアクセシビリティと検証に関する考慮事項を検討します。

途中で参照したい場合は、最終コード用のGitHubリポジトリを作成しました。

サンプルコードを取得します

マルチステップフォームの構造

求人申請書には4つのセクションがありますが、最後には要約ビューがあり、ユーザーが提出する前にすべての回答を表示します。これを達成するために、HTMLを4つのセクションに分割します。各セクションはIDで識別され、ページの下部にナビゲーションを追加します。次のセクションでそのベースラインHTMLをお伝えします。

セクションを移動するようにユーザーをナビゲートすることは、それらがどのステップであるか、残っているステップ数の視覚インジケーターも含めることを意味します。このインジケータは、アクティブなステップまたはよりファンシーな進行状況バーのタイプのインジケーターに応じて更新する単純な動的テキストにすることができます。前者は物事をシンプルに保ち、フォームのマルチステップの性質に集中します。

構造と基本的なスタイル

ロジックにもっと焦点を当てますが、最後にコードスニペットと完全なコードへのリンクを提供します。

ページを保持するフォルダーを作成することから始めましょう。次に、index.htmlファイルを作成し、次のことを貼り付けます。

HTMLを開きます

コードを見ると、3つのセクションとナビゲーショングループが表示されます。セクションにはフォーム入力が含まれており、ネイティブフォームの検証はありません。これは、ネイティブフォームの検証が[送信]ボタンをクリックするとトリガーされるため、エラーメッセージの表示をより適切に制御できるようにするためです。

次に、styles.cssファイルを作成して、それに貼り付けます:
オープンベーススタイル
<form >
  <section  >
    <div >
      <div >
        <label for="name">Name <span style="color: red;">*</span></label>
        <input type="text"  name="name" placeholder="Enter your name">
      </div>

      <div >
        <label for="idNum">ID number <span style="color: red;">*</span></label>
        <input type="number"  name="idNum" placeholder="Enter your ID number">
      </div>
    </div>

    <div >
      <div >
        <label for="email">Email <span style="color: red;">*</span></label>
        <input type="email"  name="email" placeholder="Enter your email">
      </div>

      <div >
        <label for="birthdate">Date of Birth <span style="color: red;">*</span></label>
        <input type="date"  name="birthdate" max="2006-10-01" min="1924-01-01">
      </div>
    </div>
  </section>

  <section  >
    <div >
      <label for="document">Upload CV <span style="color: red;">*</span></label>
      <input type="file" name="document" >
    </div>

    <div >
      <label for="department">Department <span style="color: red;">*</span></label>
      <select  name="department">
        <option value="">Select a department</option>
        <option value="hr">Human Resources</option>
        <option value="it">Information Technology</option>
        <option value="finance">Finance</option>
      </select>
    </div>
  </section>

  <section  >
    <div >
      <label for="skills">Skills (Optional)</label>
      <textarea  name="skills" rows="4" placeholder="Enter your skills"></textarea>
    </div>

    <div >
      <input type="checkbox" name="terms" >
      <label for="terms">I agree to the terms and conditions <span style="color: red;">*</span></label>
    </div>

    <button  type="submit">Confirm and Submit</button>
  </section>
  
  <div >
    <button type="button" >Previous</button>
    <span ></span>
    <button type="button" >Next</button>
  </div>
</form>

<script src="script.js"></script>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

ブラウザでHTMLファイルを開きます。現在のページインジケーターとナビゲーションを備えた次のスクリーンショットで2列のレイアウトのようなものを取得する必要があります。

バニラJavaScriptを使用して機能を追加します

ここで、htmlおよびcssファイルと同じディレクトリにscript.jsファイルを作成し、次のJavaScriptを貼り付けます。

ベーススクリプトを開きます
このスクリプトは、フォームセクションのIDSに対応するフォームステップ値に応じて、セクションを表示および隠すメソッドを定義します。フォームの現在のアクティブセクションでStepInfoを更新します。この動的テキストは、ユーザーへの進行状況インジケーターとして機能します。
:root {
  --primary-color: #8c852a;
  --secondary-color: #858034;
}

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

h1 {
  text-align: center;
}

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;
}

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);
}

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

.arrows {
  display: flex;
  justify-content: space-between
  align-items: center;
  margin-top: 10px;
}

#navLeft, #navRight {
  width: fit-content;
}

@media screen and (max-width: 600px) {
  .form-group {
    flex-direction: column;
  }
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
次に、ページがロードされ、イベントをクリックしてナビゲーションボタンにクリックして、さまざまなフォームセクションをサイクリングできるロジックを追加します。ページを更新すると、マルチステップフォームが期待どおりに機能することがわかります。
マルチステップフォームナビゲーション

上記のJavaScriptコードが行っていることをさらに深く掘り下げましょう。 updateStepVisibility()関数では、最初にすべてのセクションを非表示にして、きれいなスレートを持っています。

次に、現在アクティブなセクション:

を示します

次に、指標がフォームを介して進行するというテキストを更新します。

const stepInfo = document.getElementById("stepInfo");
const navLeft = document.getElementById("navLeft");
const navRight = document.getElementById("navRight");
const form = document.getElementById("myForm");
const formSteps = ["one", "two", "three"];

let currentStep = 0;

function updateStepVisibility() {
  formSteps.forEach((step) => {
    document.getElementById(step).style.display = "none";
  });

  document.getElementById(formSteps[currentStep]).style.display = "block";
  stepInfo.textContent = `Step ${currentStep + 1} of ${formSteps.length}`;
  navLeft.style.display = currentStep === 0 ? "none" : "block";
  navRight.style.display =
  currentStep === formSteps.length - 1 ? "none" : "block";
}

document.addEventListener("DOMContentLoaded", () => {
  navLeft.style.display = "none";
  updateStepVisibility();
  navRight.addEventListener("click", () => {
    if (currentStep < formSteps.length - 1) {
      currentStep++;
      updateStepVisibility();
    }
  });

  navLeft.addEventListener("click", () => {
    if (currentStep > 0) {
      currentStep--;
      updateStepVisibility();
    }
  });
});
ログイン後にコピー
ログイン後にコピー
最後に、最初のステップにいる場合は前のボタンを非表示にして、最後のセクションにある場合は次のボタンを非表示にします。

ページが読み込まれたときに何が起こるかを見てみましょう。最初のセクションにフォームが読み込まれたときに、最初に前のボタンを非表示にします:
formSteps.forEach((step) => {
  document.getElementById(step).style.display = "none";
});
ログイン後にコピー
ログイン後にコピー

次に、次のボタンをつかみ、現在のステップカウントを条件付きで増分するクリックイベントを追加し、UpdateStepVisibility()関数を呼び出します。これにより、表示される新しいセクションが更新されます。
document.getElementById(formSteps[currentStep]).style.display = "block";`
ログイン後にコピー
ログイン後にコピー

最後に、前のボタンをつかんで同じことをしますが、逆です。ここでは、ステップカウントを条件付きで減らし、updateStepVisibility()を呼び出しています:

stepInfo.textContent = `Step ${currentStep + 1} of ${formSteps.length}`;
ログイン後にコピー
ログイン後にコピー

処理エラー

navLeft.style.display = currentStep === 0 ? "none" : "block";
navRight.style.display = currentStep === formSteps.length - 1 ? "none" : "block";
ログイン後にコピー
ログイン後にコピー
これを送信するためだけにフォームに記入して、これを修正するように曖昧なエラーを取得するためだけに10分間費やしたことがありますか?フォームがすぐに何かがおかしいと言っているときにそれを好むので、

の前に

を修正できるようにします。それが私たちの形で私たちがすることです。
document.addEventListener("DOMContentLoaded", () => {
navLeft.style.display = "none";
updateStepVisibility();
ログイン後にコピー
ログイン後にコピー

私たちの原則は、どのコントロールにエラーがあるかを明確に示し、意味のあるエラーメッセージを提供することです。ユーザーが必要なアクションを実行するときにエラーをクリアします。フォームに検証を追加しましょう。まず、必要な入力要素をつかみ、これを既存の要素に追加しましょう。

navRight.addEventListener("click", () => {
  if (currentStep < formSteps.length - 1) {
    currentStep++;
    updateStepVisibility();
  }
});
ログイン後にコピー
ログイン後にコピー
次に、関数を追加して手順を検証します:

検証スクリプトを開く
<form >
  <section  >
    <div >
      <div >
        <label for="name">Name <span style="color: red;">*</span></label>
        <input type="text"  name="name" placeholder="Enter your name">
      </div>

      <div >
        <label for="idNum">ID number <span style="color: red;">*</span></label>
        <input type="number"  name="idNum" placeholder="Enter your ID number">
      </div>
    </div>

    <div >
      <div >
        <label for="email">Email <span style="color: red;">*</span></label>
        <input type="email"  name="email" placeholder="Enter your email">
      </div>

      <div >
        <label for="birthdate">Date of Birth <span style="color: red;">*</span></label>
        <input type="date"  name="birthdate" max="2006-10-01" min="1924-01-01">
      </div>
    </div>
  </section>

  <section  >
    <div >
      <label for="document">Upload CV <span style="color: red;">*</span></label>
      <input type="file" name="document" >
    </div>

    <div >
      <label for="department">Department <span style="color: red;">*</span></label>
      <select  name="department">
        <option value="">Select a department</option>
        <option value="hr">Human Resources</option>
        <option value="it">Information Technology</option>
        <option value="finance">Finance</option>
      </select>
    </div>
  </section>

  <section  >
    <div >
      <label for="skills">Skills (Optional)</label>
      <textarea  name="skills" rows="4" placeholder="Enter your skills"></textarea>
    </div>

    <div >
      <input type="checkbox" name="terms" >
      <label for="terms">I agree to the terms and conditions <span style="color: red;">*</span></label>
    </div>

    <button  type="submit">Confirm and Submit</button>
  </section>
  
  <div >
    <button type="button" >Previous</button>
    <span ></span>
    <button type="button" >Next</button>
  </div>
</form>

<script src="script.js"></script>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

ここで、必要な各入力に何らかの値があるかどうか、電子メール入力に有効な入力があるかどうかを確認します。次に、それに応じてisValidブール波を設定します。また、ShowerRor()関数を呼び出しますが、これはまだ定義されていません。

このコードをbealteStep()関数の上に貼り付けます:

:root {
  --primary-color: #8c852a;
  --secondary-color: #858034;
}

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

h1 {
  text-align: center;
}

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;
}

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);
}

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

.arrows {
  display: flex;
  justify-content: space-between
  align-items: center;
  margin-top: 10px;
}

#navLeft, #navRight {
  width: fit-content;
}

@media screen and (max-width: 600px) {
  .form-group {
    flex-direction: column;
  }
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
さて、次のスタイルをスタイルシートに追加します:

検証スタイルを開く
const stepInfo = document.getElementById("stepInfo");
const navLeft = document.getElementById("navLeft");
const navRight = document.getElementById("navRight");
const form = document.getElementById("myForm");
const formSteps = ["one", "two", "three"];

let currentStep = 0;

function updateStepVisibility() {
  formSteps.forEach((step) => {
    document.getElementById(step).style.display = "none";
  });

  document.getElementById(formSteps[currentStep]).style.display = "block";
  stepInfo.textContent = `Step ${currentStep + 1} of ${formSteps.length}`;
  navLeft.style.display = currentStep === 0 ? "none" : "block";
  navRight.style.display =
  currentStep === formSteps.length - 1 ? "none" : "block";
}

document.addEventListener("DOMContentLoaded", () => {
  navLeft.style.display = "none";
  updateStepVisibility();
  navRight.addEventListener("click", () => {
    if (currentStep < formSteps.length - 1) {
      currentStep++;
      updateStepVisibility();
    }
  });

  navLeft.addEventListener("click", () => {
    if (currentStep > 0) {
      currentStep--;
      updateStepVisibility();
    }
  });
});
ログイン後にコピー
ログイン後にコピー
フォームを更新すると、入力が有効であると見なされるまで、ボタンが次のセクションに連れて行かないことがわかります。

最後に、ユーザーが正しい情報の入力を開始したときにエラーがなくなるように、リアルタイムエラー処理を追加する必要があります。この関数をvalimatestep()関数の下に追加します:

リアルタイム検証スクリプトを開きます
この関数は、入力を聴き、イベントを変更し、関数を呼び出してエラーをクリアすることで、入力が無効でない場合、エラーをクリアします。 Showerror()1の下にclearError()関数を貼り付けます:
formSteps.forEach((step) => {
  document.getElementById(step).style.display = "none";
});
ログイン後にコピー
ログイン後にコピー

そして、ユーザーが正しい値で入力するとエラーがクリアされました:

document.getElementById(formSteps[currentStep]).style.display = "block";`
ログイン後にコピー
ログイン後にコピー
マルチステップフォームは、エラーを優雅に処理するようになりました。フォームの最後までエラーを保持することにした場合は、少なくともユーザーをエラーフォームコントロールに戻し、修正する必要があるエラーの数を示しています。

フォームの提出

マルチステップ形式では、ユーザーが提出する前に最後にすべての回答の要約を表示し、必要に応じて回答を編集するオプションを提供することが価値があります。その人は、後方にナビゲートせずに以前の手順を見ることができないため、最後のステップで要約を表示すると、保証と間違いを修正する機会が与えられます。

マークアップに4番目のセクションを追加して、この要約ビューを保持し、その中の送信ボタンを移動しましょう。これをindex.html:

の3番目のセクションのすぐ下に貼り付けます

HTMLを開きます

次に、javaScriptのフォームステップを更新して、に読み取ります
stepInfo.textContent = `Step ${currentStep + 1} of ${formSteps.length}`;
ログイン後にコピー
ログイン後にコピー
最後に、次のクラスをstyles.cssに追加します:

navLeft.style.display = currentStep === 0 ? "none" : "block";
navRight.style.display = currentStep === formSteps.length - 1 ? "none" : "block";
ログイン後にコピー
ログイン後にコピー
次に、script.jsファイルの上部に次のことを追加します。

次に、この関数をscripts.js:
document.addEventListener("DOMContentLoaded", () => {
navLeft.style.display = "none";
updateStepVisibility();
ログイン後にコピー
ログイン後にコピー
に追加します

これにより、入力値がフォームの概要セクションに動的に挿入され、ファイル名が切り捨てられ、不要な入力のフォールバックテキストが提供されます。

次に、updatestepvisibility()関数を更新して、新しい関数を呼び出します。
navRight.addEventListener("click", () => {
  if (currentStep < formSteps.length - 1) {
    currentStep++;
    updateStepVisibility();
  }
});
ログイン後にコピー
ログイン後にコピー

最後に、これをdomcontentloadedイベントリスナーに追加します:

<form >
  <section  >
    <div >
      <div >
        <label for="name">Name <span style="color: red;">*</span></label>
        <input type="text"  name="name" placeholder="Enter your name">
      </div>

      <div >
        <label for="idNum">ID number <span style="color: red;">*</span></label>
        <input type="number"  name="idNum" placeholder="Enter your ID number">
      </div>
    </div>

    <div >
      <div >
        <label for="email">Email <span style="color: red;">*</span></label>
        <input type="email"  name="email" placeholder="Enter your email">
      </div>

      <div >
        <label for="birthdate">Date of Birth <span style="color: red;">*</span></label>
        <input type="date"  name="birthdate" max="2006-10-01" min="1924-01-01">
      </div>
    </div>
  </section>

  <section  >
    <div >
      <label for="document">Upload CV <span style="color: red;">*</span></label>
      <input type="file" name="document" >
    </div>

    <div >
      <label for="department">Department <span style="color: red;">*</span></label>
      <select  name="department">
        <option value="">Select a department</option>
        <option value="hr">Human Resources</option>
        <option value="it">Information Technology</option>
        <option value="finance">Finance</option>
      </select>
    </div>
  </section>

  <section  >
    <div >
      <label for="skills">Skills (Optional)</label>
      <textarea  name="skills" rows="4" placeholder="Enter your skills"></textarea>
    </div>

    <div >
      <input type="checkbox" name="terms" >
      <label for="terms">I agree to the terms and conditions <span style="color: red;">*</span></label>
    </div>

    <button  type="submit">Confirm and Submit</button>
  </section>
  
  <div >
    <button type="button" >Previous</button>
    <span ></span>
    <button type="button" >Next</button>
  </div>
</form>

<script src="script.js"></script>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
フォームを実行しているそして今、フォームを送信できます:

マルチステップフォームを使用すると、ユーザーが送信する前に提供するすべての情報を編集して確認できるようになりました。
:root {
  --primary-color: #8c852a;
  --secondary-color: #858034;
}

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

h1 {
  text-align: center;
}

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;
}

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);
}

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

.arrows {
  display: flex;
  justify-content: space-between
  align-items: center;
  margin-top: 10px;
}

#navLeft, #navRight {
  width: fit-content;
}

@media screen and (max-width: 600px) {
  .form-group {
    flex-direction: column;
  }
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
アクセシビリティのヒント

マルチステップフォームをアクセス可能にすることは、基本から始まります:

セマンティックHTMLを使用します。

これは戦いの半分です。適切なフォームラベルを使用して密接に続いています フォームをよりアクセスしやすいものにする他の方法には、小さな画面でクリックする必要がある要素に十分なスペースを与えることと、フォームナビゲーションと進行状況の指標に意味のある説明を与える必要があります。

ユーザーへのフィードバックを提供することは、その重要な部分です。一定の時間を経てユーザーのフィードバックを自動するのはあまりありませんが、ユーザーが自分でそれを却下できるようにすることは素晴らしいことではありません。コントラストとフォントの選択に注意を払うことも重要です。どちらもあなたのフォームがどれほど読みやすいかに影響を与えるためです。

より技術的なアクセシビリティを得るために、マークアップに次の調整を行いましょう:

スキルを除くすべての入力にaria-required = "true"を追加します。

エラースパンにロール= "アラート"を追加します。

ロール= "status" aria-live = "polite" to g.stepinfo。

これは、スクリーン読者がステップ情報が状態のタブを保持することを理解するのに役立ちます。
    ここでは、入力をエラースパンで明示的に結びつける属性をプログラム的に追加および削除し、それが無効な状態にあることを示します。 最後に、すべてのセクションの最初の入力に焦点を合わせましょう。 updatePvisibility()関数の最後に次のコードを追加します:
  1. そしてそれで、マルチステップフォームははるかにアクセスしやすいです。 結論
  2. ジョブアプリケーション用の4部構成のマルチステップフォームに行きます!この記事の一番上で言ったように、ジャグリングすることはたくさんあります。そのため、すぐに使えるソリューションを探してもあなたを責めることはありません。 しかし、マルチステップフォームをハンドロールする必要がある場合、それが死刑判決ではないことを願っています。良い、アクセス可能なプラクティスから背を向けることなく、ナビゲーションと検証を完了することで、あなたをそこに連れて行く幸せな道があります。

    そしてこれが私がそれにアプローチした方法です!繰り返しますが、私はこれを個人的な挑戦として引き受け、どこまで手に入れることができるかを確認しました。しかし、これをユーザーエクスペリエンスとアクセシビリティの思いやりにさらに念頭に置くための追加の機会があるかどうかを知りたいです。

    参照

    この記事を書く際に言及したいくつかの関連するリンクがあります:

      Webフォームの構造(MDN)
    1. マルチページフォーム(w3c.org)
    2. アクセス可能なフォームを作成(A11yプロジェクト)

以上がバニラJavaScriptとCSSでマルチステップフォームを作成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート