Table of Contents
Perché i moduli multi-Step sono una scelta intelligente per la raccolta dati di User‐Friendly
L'abbattimento di un modulo in passaggi logici – uno schermo alla volta – riduce il carico cognitivo e rende il processo più maneggevole. Multi-step forma gli utenti guida attraverso ogni pezzo di informazione senza schiacciarli, che migliora i tassi di completamento e la qualità dei dati.
Dal punto di vista tecnico, JavaScript ti dà la flessibilità di nascondere e mostrare le sezioni, convalidare l'ingresso prima di andare avanti e fornire feedback immediato.Quando combinato con una corretta validazione, moduli multi-step può garantire che solo i dati puliti e precisi vengano inviati al server.
In questo articolo imparerai a costruire un robusto modulo multi-step utilizzando il JavaScript vaniglia, tra cui la navigazione, la validazione lato client, gli indicatori di progresso e le migliori pratiche di accessibilità.
Struttura centrale di un modulo multi-Step
Ogni forma multi-step segue un modello simile:
- Un contenitore forma] che avvolge tutti i passi
- Le sezioni passo-passo semplici[ – ogni passo è un che diventa visibile o nascosto
- I pulsanti di navigazione[[ – “Next” e “Previous” per muoversi tra i passaggi
- La logica di valutazione[[] – verifica che i campi nella fase corrente sono validi prima di consentire all'utente di procedere
È inoltre possibile aggiungere un indicatore di progresso[] (ad esempio, numeri di passo o una barra di progresso) per mostrare agli utenti dove sono e quanto rimane.
Costruire la Shell HTML
Ogni passo è un ] con una classe di . Solo il primo passo è visibile per impostazione predefinita; gli altri sono nascosti con .
<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>
Important:[]] Usa per i pulsanti di navigazione per evitare l'invio accidentale del modulo. Solo il pulsante finale “Submit” dovrebbe avere .
CSS: Gestione della visibilità e dello stiramento
Invece di contare su inline [], è più pulito usare le classi CSS.
.step {
display: none;
}
.step.active {
display: block;
}
Quindi nel HTML, rimuovere gli attributi in linea [] e aggiungere solo al primo passo. JavaScript toggle the ] classe per mostrare / nascondere passi.
È inoltre possibile aggiungere transizioni, barre di progresso e spaziatura coerente.
.step {
opacity: 0;
transition: opacity 0.3s ease;
}
.step.active {
opacity: 1;
display: block;
}
Questo crea un effetto sbiadito liscio durante la commutazione dei passi.
JavaScript: Navigazione e Validazione
Ora scriveremo la logica fondamentale: traslocare tra i passi, convalidare i campi di ogni passo e aggiornare l'interfaccia utente.
Selezione di elementi DOM
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
Funzioni di navigazione
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);
}
Validazione per passo
Scrivere una funzione che controlla tutti i campi richiesti nel passo corrente e visualizza messaggi di errore. Per semplicità, useremo in questo esempio, ma un modulo di produzione dovrebbe mostrare messaggi di errore in linea accanto ai campi.
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());
}
Attaccare gli ascoltatori degli eventi
nextBtns.forEach(btn => btn.addEventListener('click', nextStep));
prevBtns.forEach(btn => btn.addEventListener('click', prevStep));
Nota:[]] Questo presuppone che ogni passo abbia esattamente un “Next” e un “Previous” pulsante. Per forme più complesse, potresti voler usare attributi di dati (ad esempio, ) per mappare i pulsanti a passaggi specifici.
Tecniche di convalida avanzate
Mentre i controlli base richiesti-campo sono essenziali, le forme moderne beneficiano di una validazione più sofisticata che migliora l'esperienza utente e la qualità dei dati.
Convalida di Constraint HTML5
I browser moderni supportano la validazione integrata per ], , [], , ecc. È possibile sfruttare il metodo e la pseudo-classe per lo 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;
}
Validazione in linea in tempo reale
Per dare agli utenti un feedback immediato come si digitano, ascoltare gli eventi o su singoli campi.
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');
}
});
Convalida Regex personalizzata
Per i campi come numeri di telefono, codici postali o password, utilizzare [] attributi o regex personalizzato. Esempio per un numero di telefono americano (10 cifre):
<input type="tel" id="phone" name="phone" pattern="\d{3}-\d{3}-\d{4}" placeholder="123-456-7890" />
Poi in JavaScript, è possibile controllare ] o testare il valore con il proprio regex.
Aggiungere un indicatore di progresso
Una barra di progresso o un contapassi aiuta gli utenti a capire quanti passi rimangono e riduce l'ansia.
Struttura HTML per passi di progresso
<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;
}
Aggiornamento JavaScript
All'interno della funzione , anche aggiornare gli indicatori di progresso:
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;
}
È inoltre possibile aggiungere una barra di progresso lineare calcolando la percentuale: e impostando la larghezza di un .
Gestione dei casi e dell'esperienza utente
Per costruire una forma multi-step di produzione, consideri questi aspetti aggiuntivi:
Navigazione tastiera
Gli utenti dovrebbero essere in grado di andare avanti con il tasto Enter] (trigger il “Next” pulsante) e indietro con [Escape[]] o una scorciatoia dedicata.
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();
}
});
Prevenire più sottomissioni
Disattivare il pulsante di presentazione dopo il primo clic per evitare le presentazioni dei moduli duplicati:
const submitBtn = document.querySelector('button[type="submit"]');
submitBtn.addEventListener('click', function() {
this.disabled = true;
this.textContent = 'Submitting…';
// The form will submit naturally after this
});
Memorizzazione dei dati Temporaneamente
Se l'utente aggiorna accidentalmente la pagina, perde tutti i dati inseriti. Considerare la memorizzazione dei valori di campo in [ o come l'utente procede. Sul carico di pagina, ripristinare i valori e saltare all'ultimo passaggio salvato.
Considerazioni di sicurezza
La validazione lato client è solo per l'esperienza utente; convalidare e sanificare sempre i dati sul server.
Accessibilità (A11y) Migliori Pratiche
Le forme multi-step possono essere difficili per gli utenti di screen-reader se non codificati correttamente.
- Usa e ] per raggruppare ogni passo logicamente.
- Annuncia le modifiche di passo utilizzando ARIA regioni dal vivo[] (ad esempio ]) così i lettori di schermo sanno che è apparso nuovo contenuto.
- Aggiungi al passo di progresso corrente.
- Assicurare che i messaggi di errore siano associati programmaticamente ai campi di input (utilizzare ).
- Assicurarsi che tutti gli elementi interattivi siano accessibili alla tastiera e abbiano indicatori di messa a fuoco visibili.
<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>
Quando la convalida non riesce, inserire il messaggio di errore nel e verrà annunciato.
Portare tutto insieme: un esempio completo
Di seguito è riportata una versione condensata di una forma multi-step completamente funzionale con validazione e un indicatore di progresso.
<!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>
Questo esempio utilizza la validazione HTML5 ([[]) e i messaggi di errore incorporati. È possibile sostituire con la formattazione di errore personalizzato se necessario.
Ulteriori letture e risorse
Per approfondire la comprensione della convalida e dell'accessibilità dei moduli, controlla queste risorse:
- MDN: Convalida del modulo client[
- WAI Web Accessibility: Multi-Page Forms
- MDN: ARIA Live Regioni[
- Blog di Directus: Costruire forme migliori[] (per idee di integrazione backend)
Sbagliare
Le forme multi-step realizzate con JavaScript sono uno strumento potente per migliorare l'esperienza dell'utente e l'accuratezza dei dati. Inserire una forma lunga in sezioni gestibili, convalidare l'ingresso ad ogni passo e fornire spunti di progresso visivo, è possibile ridurre drasticamente l'abbandono del modulo e raccogliere dati più puliti.
Inizia con una solida struttura HTML, strato in CSS per feedback visivi, e poi aggiungi JavaScript per la navigazione e la validazione. Espandi il tuo modulo con validazione in tempo reale, indicatori di progresso e funzionalità di accessibilità per renderlo utilizzabile per tutti. Infine, ricorda sempre che la validazione lato client è una convenienza – non contare mai su di esso da solo.
Sperimenta con diversi progetti e tecniche di validazione per soddisfare le esigenze della tua applicazione. Le tecniche qui mostrate forniscono una base che puoi adattare e estendere per qualsiasi progetto di forma multi-step.