Table of Contents
Waarom Multi-Stap formulieren een slimme keuze zijn voor gebruikersvriendelijke gegevensverzameling
Lange, single-page formulieren vaak frustreren gebruikers en leiden tot hogere verlatingsgraden. Breken van een vorm in logische stappen een scherm per keer . . vermindert cognitieve belasting en maakt het proces beheersbaarer. Multi-stap vormen leiden gebruikers door elk stuk informatie zonder overweldigend hen, die verbetert voltooiings- en datakwaliteit.
Vanuit technisch oogpunt geeft JavaScript u de flexibiliteit om secties te verbergen en te tonen, input te valideren voordat u verder gaat, en onmiddellijke feedback te geven. Wanneer dit gecombineerd wordt met een juiste validatie, kunnen multi-stap formulieren ervoor zorgen dat alleen schone, nauwkeurige gegevens aan uw server worden doorgegeven.
In dit artikel leert u hoe u een robuuste multi-stap formulier kunt bouwen met behulp van vanille JavaScript, inclusief navigatie, cliënt-validatie, voortgangsindicatoren en beste praktijken voor toegankelijkheid.
Kernstructuur van een multi-stap-formulier
Elke vorm van meerstappen volgt een soortgelijk patroon:
- Een vormcontainer die alle stappen omwikkelt
- Meerdere stapsecties Elke stap is een die zichtbaar of verborgen wordt
- Navigatieknoppen
- Validatielogica
U kunt ook een vooruitgangsindicator (bijv. stapnummers of een voortgangsbalk) toevoegen om gebruikers te laten zien waar ze zijn en hoeveel er nog over is.
De HTML Shell bouwen
Begin met een schone HTML-structuur. Elke stap is een met een klasse van . Alleen de eerste stap is standaard zichtbaar; de andere stappen zijn verborgen met .
<form id="multiStepForm">
<!-- Step 1: Personal Information -->
<div class="step active" id="step1">
<h3>Step 1: Personal Information</h3>
<label for="name">Full Name</label>
<input type="text" id="name" name="name" required />
<button type="button" class="next-btn">Next</button>
</div>
<!-- Step 2: Contact Details -->
<div class="step" id="step2" style="display:none">
<h3>Step 2: Contact Details</h3>
<label for="email">Email Address</label>
<input type="email" id="email" name="email" required />
<label for="phone">Phone Number</label>
<input type="tel" id="phone" name="phone" />
<button type="button" class="prev-btn">Previous</button>
<button type="button" class="next-btn">Next</button>
</div>
<!-- Step 3: Confirmation -->
<div class="step" id="step3" style="display:none">
<h3>Step 3: Review & Submit</h3>
<p>Please review your information before submitting.</p>
<button type="button" class="prev-btn">Previous</button>
<button type="submit">Submit</button>
</div>
</form>
Belangrijk: Gebruik voor navigatieknoppen om onbedoelde indiening van formulieren te voorkomen. Alleen de laatste
CSS: Zichtbaarheid en Styling beheren
In plaats van te vertrouwen op inline , is het schoner om CSS-klassen te gebruiken. Voeg het volgende toe aan je stylesheet:
.step {
display: none;
}
.step.active {
display: block;
}
Verwijder vervolgens in de HTML de inline attributen en voeg alleen toe aan de eerste stap. JavaScript zal de klasse aan-/verbergen om stappen te tonen.
Je kunt ook overgangen, voortgangsbalken en consistente afstand toevoegen. Bijvoorbeeld:
.step {
opacity: 0;
transition: opacity 0.3s ease;
}
.step.active {
opacity: 1;
display: block;
}
Dit zorgt voor een soepel fade-in effect bij het schakelen van stappen.
JavaScript: Navigatie en Validatie
Nu schrijven we de kernlogica: bewegen tussen stappen, valideren van elke stap .. velden, en het bijwerken van de UI.
DOM-elementen selecteren
const steps = document.querySelectorAll('.step');
const nextBtns = document.querySelectorAll('.next-btn');
const prevBtns = document.querySelectorAll('.prev-btn');
let currentStep = 0; // index of the currently visible step
Navigatiefuncties
function showStep(stepIndex) {
steps.forEach((step, index) => {
step.classList.toggle('active', index === stepIndex);
});
currentStep = stepIndex;
}
function nextStep() {
if (validateStep(currentStep)) {
showStep(currentStep + 1);
}
}
function prevStep() {
showStep(currentStep - 1);
}
Validatie per stap
Schrijf een functie die alle benodigde velden controleert in de huidige stap en geeft foutmeldingen weer. Voor eenvoud gebruiken we in dit voorbeeld, maar een productieformulier moet inline foutmeldingen naast de velden tonen.
function validateStep(stepIndex) {
const currentStepDiv = steps[stepIndex];
const inputs = currentStepDiv.querySelectorAll('input[required]');
for (let input of inputs) {
if (!input.value.trim()) {
alert(`Please fill in "${input.placeholder || input.name}".`);
input.focus();
return false;
}
// Additional validation per type can be added here
if (input.type === 'email' && !isValidEmail(input.value)) {
alert('Please enter a valid email address.');
input.focus();
return false;
}
}
return true;
}
function isValidEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(email.trim());
}
Bijvoegen van evenementenluisteraars
nextBtns.forEach(btn => btn.addEventListener('click', nextStep));
prevBtns.forEach(btn => btn.addEventListener('click', prevStep));
Opmerking: Dit veronderstelt dat elke stap precies één
Geavanceerde validatietechnieken
Hoewel fundamentele controles op het vereiste terrein essentieel zijn, profiteren moderne formulieren van meer geavanceerde validaties die gebruikerservaring en gegevenskwaliteit verbeteren.
HTML5 Constraint-validatie
Moderne browsers ondersteunen ingebouwde validatie voor , , , enz. U kunt gebruikmaken van de methode en de pseudo-klasse ] voor styling.
function validateStepHTML5(stepIndex) {
const currentStepDiv = steps[stepIndex];
const inputs = currentStepDiv.querySelectorAll('input, select, textarea');
for (let input of inputs) {
if (!input.checkValidity()) {
input.reportValidity(); // shows the browser's native error tooltip
return false;
}
}
return true;
}
Real-time inline-validatie
Om gebruikers onmiddellijk feedback te geven wanneer ze typen, luistert u naar of gebeurtenissen op individuele velden. Bijvoorbeeld:
const emailInput = document.getElementById('email');
emailInput.addEventListener('blur', function() {
if (this.value && !isValidEmail(this.value)) {
this.classList.add('invalid');
// show an error message next to the field
} else {
this.classList.remove('invalid');
}
});
Aangepaste Regex-validatie
Voor velden zoals telefoonnummers, postcodes of wachtwoorden, gebruik .9.] attributen of aangepaste regex. Voorbeeld voor een US telefoonnummer (10 cijfers):
<input type="tel" id="phone" name="phone" pattern="\d{3}-\d{3}-\d{4}" placeholder="123-456-7890" />
Dan kunt u in JavaScript controleren of de waarde testen met uw eigen regex.
Een voortgangsindicator toevoegen
Een voortgangsbalk of stapteller helpt gebruikers te begrijpen hoeveel stappen er nog over zijn en vermindert angst. Hier een eenvoudige implementatie met JavaScript en CSS.
HTML-structuur voor voortgangsstappen
<div id="progress">
<span class="progress-step active">1</span>
<span class="progress-step">2</span>
<span class="progress-step">3</span>
</div>
CSS-styling
.progress-step {
display: inline-block;
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
border-radius: 50%;
background: #ccc;
color: #fff;
}
.progress-step.active {
background: #007bff;
}
JavaScript-update
Binnen de functie worden de voortgangsindicatoren ook bijgewerkt:
function showStep(stepIndex) {
steps.forEach((step, index) => {
step.classList.toggle('active', index === stepIndex);
});
document.querySelectorAll('.progress-step').forEach((el, index) => {
el.classList.toggle('active', index === stepIndex);
});
currentStep = stepIndex;
}
U kunt ook een lineaire voortgangsbalk toevoegen door het percentage te berekenen: en de breedte van een in te stellen.
Behandeling Rand gevallen en gebruikerservaring details
Om een meerfasenvorm voor productie te ontwikkelen, moet rekening worden gehouden met deze aanvullende aspecten:
Navigatie van toetsenbord
Gebruikers moeten in staat zijn om vooruit te gaan met de Enter sleutel (trigger de
document.addEventListener('keydown', function(e) {
if (e.key === 'Enter' && e.target.closest('.step.active')) {
const nextBtn = document.querySelector('.step.active .next-btn');
if (nextBtn) nextBtn.click();
}
});
Meerdere indieningen voorkomen
Schakel de knop verzenden na de eerste klik om dubbele formulier indieningen te voorkomen:
const submitBtn = document.querySelector('button[type="submit"]');
submitBtn.addEventListener('click', function() {
this.disabled = true;
this.textContent = 'Submitting…';
// The form will submit naturally after this
});
Gegevens tijdelijk opslaan
Als de gebruiker de pagina per ongeluk ververst, verliezen ze alle ingevoerde gegevens. Overweeg het opslaan van veldwaarden in of naarmate de gebruiker vordert. Op pagina laden, herstel de waarden en spring naar de laatst opgeslagen stap.
Veiligheidsoverwegingen
De validatie aan de clientzijde is alleen bedoeld voor gebruikerservaring; altijd valideren en de gegevens op de server sanitiseren. Gebruik HTTPS en overwegen om CSRF tokens toe te voegen voor gevoelige formulieren.
Toegankelijkheid (A11y) Beste praktijken
Multistap formulieren kunnen voor schermlezergebruikers uitdagen als ze niet correct gecodeerd zijn. Volg de volgende richtlijnen:
- Gebruik en om elke stap logisch te groeperen.
- Vertel stapwijzigingen met ARIA live regions (bijv. ) zodat schermlezers weten dat er nieuwe inhoud verscheen.
- Voeg toe aan de huidige voortgangsstap.
- Zorg ervoor dat foutmeldingen programmatisch worden geassocieerd met de invoervelden (gebruik ).
- Zorg ervoor dat alle interactieve elementen toegankelijk zijn voor toetsenbord en zichtbare focusindicatoren hebben.
<div class="step active" id="step1" aria-live="polite">
<h3>Step 1 of 3: Personal Information</h3>
<label for="name">Full Name</label>
<input type="text" id="name" name="name" required />
<span id="name-error" class="error" role="alert"></span>
</div>
Als de validatie mislukt, plaatst u het foutbericht in de en wordt het aangekondigd.
Het geheel samenbrengen: Een compleet voorbeeld
Hieronder vindt u een gecondenseerde versie van een volledig functionele multi-stap vorm met validatie en een voortgangsindicator. U kunt deze structuur aanpassen aan uw eigen projecten.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Multi‑Step Form with Validation</title>
<style>
.step { display: none; }
.step.active { display: block; }
.progress-step { background: #ccc; padding: 5px 10px; margin: 0 2px; }
.progress-step.active { background: #007bff; color: #fff; }
.error { color: red; font-size: 0.9em; }
</style>
</head>
<body>
<form id="multiStepForm" novalidate>
<div id="progress">
<span class="progress-step active">1</span>
<span class="progress-step">2</span>
<span class="progress-step">3</span>
</div>
<div class="step active" id="step1">
<h3>Step 1: Personal Information</h3>
<label for="name">Full Name *</label>
<input type="text" id="name" name="name" required minlength="2">
<button type="button" class="next-btn">Next</button>
</div>
<div class="step" id="step2">
<h3>Step 2: Contact Details</h3>
<label for="email">Email *</label>
<input type="email" id="email" name="email" required>
<button type="button" class="prev-btn">Previous</button>
<button type="button" class="next-btn">Next</button>
</div>
<div class="step" id="step3">
<h3>Step 3: Submit</h3>
<p>Review your details and submit.</p>
<button type="button" class="prev-btn">Previous</button>
<button type="submit">Submit</button>
</div>
</form>
<script>
const steps = document.querySelectorAll('.step');
const nextBtns = document.querySelectorAll('.next-btn');
const prevBtns = document.querySelectorAll('.prev-btn');
const progressSteps = document.querySelectorAll('.progress-step');
let currentStep = 0;
function showStep(index) {
steps.forEach((step, i) => step.classList.toggle('active', i === index));
progressSteps.forEach((step, i) => step.classList.toggle('active', i === index));
currentStep = index;
}
function validateCurrentStep() {
const stepDiv = steps[currentStep];
const inputs = stepDiv.querySelectorAll('input[required]');
for (let input of inputs) {
if (!input.checkValidity()) {
input.reportValidity();
return false;
}
}
return true;
}
nextBtns.forEach(btn => {
btn.addEventListener('click', function(e) {
if (validateCurrentStep()) {
showStep(currentStep + 1);
}
});
});
prevBtns.forEach(btn => {
btn.addEventListener('click', function(e) {
showStep(currentStep - 1);
});
});
// Optional: handle Enter key
document.addEventListener('keydown', function(e) {
if (e.key === 'Enter' && e.target.closest('.step.active')) {
const nextBtn = document.querySelector('.step.active .next-btn');
if (nextBtn) nextBtn.click();
}
});
</script>
</body>
</html>
Dit voorbeeld gebruikt HTML5-validatie () en de ingebouwde foutmeldingen. U kunt vervangen door aangepaste foutopmaak indien nodig.
Verdere lezing en bronnen
Om uw begrip van vormvalidatie en toegankelijkheid te verdiepen, controleer deze bronnen:
- MDN: Client-side-formvalidatie
- WAI Web Toegankelijkheidstutorials: Multi-Page Forms
- MDN: ARIA Live Regions
- Directus Blog: Betere vormen bouwen (voor ideeën voor backend-integratie)
Omwikkelen
Multi-stap formulieren gebouwd met JavaScript zijn een krachtig hulpmiddel voor het verbeteren van de gebruikerservaring en de nauwkeurigheid van gegevens. Door een lange vorm te breken in beheersbare secties, de input bij elke stap te valideren, en visuele vooruitgang te bieden, kunt u de vorm verlaten drastisch verminderen en schonere gegevens verzamelen.
Begin met een solide HTML-structuur, laag in CSS voor visuele feedback en voeg JavaScript toe voor navigatie en validatie. Breid uw formulier uit met realtime validatie, voortgangsindicatoren en toegankelijkheidskenmerken om het voor iedereen bruikbaar te maken. Tot slot, vergeet niet dat cliënt-side validatie een gemak is . Vertrouw er nooit op alleen. Valideer alle gegevens op de server ook.
Experimenteer met verschillende ontwerpen en validatietechnieken om aan uw behoeften te voldoen. De technieken die hier getoond worden, bieden een basis die u kunt aanpassen en uitbreiden voor elk multi-stap project.