SnippetUI

Multi-Step-Formular

Eine Formular-Komponente zur Navigation durch mehrere Schritte, ideal für Registrierungsprozesse, inklusive einer integrierten Fortschrittsanzeige.

HTMLTailwind CSSJavaScript

Ein mehrstufiges Formular im Wizard-Stil, das besonders bei langen Eingabeprozessen wie Registrierungen oder Umfragen eingesetzt wird. Es verfügt über eine Fortschrittsanzeige zur visuellen Darstellung des aktuellen Schritts sowie flüssige Slide-Animationen für eine verbesserte Benutzererfahrung.

Vorschau

1
Account
2
Personal
3
Review

Account Info

Please enter the information used for login.

Personal Info

Please provide your basic information.

Confirm your entry

You will be registered with the following details. Is this correct?

Email Addressyou@example.com
NameJohn Doe
Phone Number090-1234-5678

Anwendungsfälle und Funktionen

  • Benutzerregistrierung und Onboarding: Durch das Aufteilen vieler Eingabefelder auf mehrere Schritte wird die psychologische Hürde für den Nutzer gesenkt und die Abbruchquote minimiert.
  • Organisation komplexer Formulare: Reduziert die kognitive Belastung, indem umfangreiche Abfragen – wie bei Versandinformationen oder Umfragen – in logische Abschnitte gegliedert werden.
  • Fortschrittsvisualisierung: Der Fortschrittsbalken am oberen Rand zeigt den Nutzern genau, in welchem Schritt sie sich befinden und wie viele noch folgen, was für zusätzliche Klarheit sorgt.

Design & UX

  • Flüssige Slide-Animationen: Beim Wechsel zwischen den Schritten gleiten die Inhalte sanft nach links oder rechts und blenden ein bzw. aus, was ein Gefühl von räumlicher Kontinuität vermittelt.
  • Klares Status-Feedback: Abgeschlossene Schritte werden mit einem Häkchen markiert, während der aktuelle Schritt optisch durch einen Ring hervorgehoben wird, wodurch der Fortschritt intuitiv erfassbar ist.
  • Aktionsorientierte Buttons: Beim Erreichen des letzten Schritts ändert sich die Farbe des “Weiter”-Buttons zu Grün (emerald), und der Text wechselt zu “Senden”, um die endgültige Aktion eindeutig zu signalisieren.

Anpassungsanleitung

  • Anpassung der Markenfarben: Sie können das Farbschema leicht an Ihr Projekt anpassen, indem Sie Klassen wie indigo-600 durch Ihre eigenen Markenfarben (z. B. blue-600 oder rose-500) ersetzen.
  • Anzahl der Schritte ändern: Die Anzahl der Schritte lässt sich flexibel anpassen, indem Sie im HTML-Code weitere Sets von <div class="msf-step-indicator">...</div> und <div class="msf-step-content">...</div> hinzufügen oder entfernen und im JavaScript das Array const steps = [1, 2, 3]; aktualisieren.
  • Validierung integrieren: Für den produktiven Einsatz können Sie im Click-Event des “Weiter”-Buttons (btnNext.addEventListener) eine Eingabevalidierung (Pflichtfelder, Formatprüfung usw.) für den jeweiligen Schritt einbauen und currentStep++ nur bei erfolgreicher Prüfung ausführen.

Implementierung

<div class="multi-step-form-wrapper bg-gray-50 flex items-center justify-center p-6 min-h-[600px] font-sans">
<div class="bg-white rounded-2xl shadow-xl w-full max-w-lg p-8 relative overflow-hidden border border-gray-100">
  <!-- Progress Bar -->
  <div class="flex justify-between items-center mb-10 relative">
    <div class="absolute left-0 top-1/2 transform -translate-y-1/2 w-full h-1.5 bg-gray-200 z-0 rounded-full"></div>
    <div id="msf-progress-bar" class="absolute left-0 top-1/2 transform -translate-y-1/2 h-1.5 bg-indigo-600 z-0 transition-all duration-500 ease-out rounded-full" style="width: 0%;"></div>
    
    <!-- Step 1 -->
    <div class="relative z-10 flex flex-col items-center">
      <div class="msf-step-indicator w-10 h-10 rounded-full flex items-center justify-center font-bold transition-all duration-500 bg-indigo-600 text-white shadow-md border-4 border-white ring-4 ring-indigo-100" data-step="1">1</div>
      <span class="msf-step-label text-xs font-bold text-indigo-600 mt-2 transition-colors duration-300 tracking-wide uppercase">Account</span>
    </div>
    <!-- Step 2 -->
    <div class="relative z-10 flex flex-col items-center">
      <div class="msf-step-indicator w-10 h-10 rounded-full flex items-center justify-center font-bold transition-all duration-500 bg-gray-200 text-gray-500 border-4 border-white" data-step="2">2</div>
      <span class="msf-step-label text-xs font-medium text-gray-400 mt-2 transition-colors duration-300 tracking-wide uppercase">Personal</span>
    </div>
    <!-- Step 3 -->
    <div class="relative z-10 flex flex-col items-center">
      <div class="msf-step-indicator w-10 h-10 rounded-full flex items-center justify-center font-bold transition-all duration-500 bg-gray-200 text-gray-500 border-4 border-white" data-step="3">3</div>
      <span class="msf-step-label text-xs font-medium text-gray-400 mt-2 transition-colors duration-300 tracking-wide uppercase">Review</span>
    </div>
  </div>

  <!-- Form Steps -->
  <div class="relative h-[280px] overflow-visible">
    <!-- Step 1 Content -->
    <div class="msf-step-content absolute w-full transition-all duration-500 transform translate-x-0 opacity-100" data-step="1">
      <h2 class="text-2xl font-extrabold text-gray-900 mb-2">Account Info</h2>
      <p class="text-sm text-gray-500 mb-6">Please enter the information used for login.</p>
      <div class="space-y-4">
        <div>
          <label class="block text-sm font-semibold text-gray-700 mb-1.5">Email Address</label>
          <input type="email" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none transition-all shadow-sm bg-gray-50 focus:bg-white" placeholder="you@example.com" />
        </div>
        <div>
          <label class="block text-sm font-semibold text-gray-700 mb-1.5">Password</label>
          <input type="password" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none transition-all shadow-sm bg-gray-50 focus:bg-white" placeholder="••••••••" />
        </div>
      </div>
    </div>

    <!-- Step 2 Content -->
    <div class="msf-step-content absolute w-full transition-all duration-500 transform translate-x-12 opacity-0 pointer-events-none" data-step="2">
      <h2 class="text-2xl font-extrabold text-gray-900 mb-2">Personal Info</h2>
      <p class="text-sm text-gray-500 mb-6">Please provide your basic information.</p>
      <div class="space-y-4">
        <div class="grid grid-cols-2 gap-4">
          <div>
            <label class="block text-sm font-semibold text-gray-700 mb-1.5">Last Name</label>
            <input type="text" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none transition-all shadow-sm bg-gray-50 focus:bg-white" placeholder="John" />
          </div>
          <div>
            <label class="block text-sm font-semibold text-gray-700 mb-1.5">First Name</label>
            <input type="text" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none transition-all shadow-sm bg-gray-50 focus:bg-white" placeholder="Doe" />
          </div>
        </div>
        <div>
          <label class="block text-sm font-semibold text-gray-700 mb-1.5">Phone Number</label>
          <input type="tel" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none transition-all shadow-sm bg-gray-50 focus:bg-white" placeholder="090-1234-5678" />
        </div>
      </div>
    </div>

    <!-- Step 3 Content -->
    <div class="msf-step-content absolute w-full transition-all duration-500 transform translate-x-12 opacity-0 pointer-events-none" data-step="3">
      <h2 class="text-2xl font-extrabold text-gray-900 mb-2">Confirm your entry</h2>
      <p class="text-sm text-gray-500 mb-6">You will be registered with the following details. Is this correct?</p>
      <div class="bg-gray-50/80 backdrop-blur-sm rounded-xl p-5 border border-gray-100 shadow-inner space-y-4 text-sm">
        <div class="flex justify-between items-center border-b border-gray-200 pb-3">
          <span class="text-gray-500 font-medium">Email Address</span>
          <span class="font-bold text-gray-800">you@example.com</span>
        </div>
        <div class="flex justify-between items-center border-b border-gray-200 pb-3">
          <span class="text-gray-500 font-medium">Name</span>
          <span class="font-bold text-gray-800">John Doe</span>
        </div>
        <div class="flex justify-between items-center">
          <span class="text-gray-500 font-medium">Phone Number</span>
          <span class="font-bold text-gray-800">090-1234-5678</span>
        </div>
      </div>
    </div>
  </div>

  <!-- Buttons -->
  <div class="flex justify-between mt-8 pt-6 border-t border-gray-100 relative z-10">
    <button id="msf-btn-prev" class="px-6 py-2.5 border border-gray-300 text-gray-700 font-bold rounded-xl hover:bg-gray-50 hover:text-indigo-600 focus:outline-none focus:ring-2 focus:ring-gray-200 transition-all duration-300 opacity-0 pointer-events-none disabled:opacity-50 flex items-center justify-center gap-2">
      <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg>
      Back
    </button>
    <button id="msf-btn-next" class="px-6 py-2.5 bg-indigo-600 text-white font-bold rounded-xl hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-all duration-300 ml-auto shadow-[0_4px_14px_0_rgba(79,70,229,0.39)] hover:shadow-[0_6px_20px_rgba(79,70,229,0.23)] hover:-translate-y-0.5 flex items-center justify-center gap-2 active:translate-y-0">
      Next
      <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
    </button>
  </div>
</div>
</div>

<script>
(function() {
  const steps = [1, 2, 3];
  let currentStep = 1;
  
  const progressBar = document.getElementById('msf-progress-bar');
  const indicators = document.querySelectorAll('.msf-step-indicator');
  const labels = document.querySelectorAll('.msf-step-label');
  const contents = document.querySelectorAll('.msf-step-content');
  const btnPrev = document.getElementById('msf-btn-prev');
  const btnNext = document.getElementById('msf-btn-next');
  
  if (!progressBar) return;

  function updateUI() {
    const progressPercentage = ((currentStep - 1) / (steps.length - 1)) * 100;
    progressBar.style.width = `${progressPercentage}%`;
    
    indicators.forEach((ind, index) => {
      const stepNum = index + 1;
      const label = labels[index];
      
      if (stepNum < currentStep) {
        ind.className = "msf-step-indicator w-10 h-10 rounded-full flex items-center justify-center font-bold transition-all duration-500 bg-indigo-600 text-white shadow-md border-4 border-white";
        ind.innerHTML = `<svg class="w-5 h-5 animate-pulse" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M5 13l4 4L19 7"></path></svg>`;
        label.className = "msf-step-label text-xs font-bold text-indigo-600 mt-2 transition-colors duration-300 tracking-wide uppercase";
      } else if (stepNum === currentStep) {
        ind.className = "msf-step-indicator w-10 h-10 rounded-full flex items-center justify-center font-bold transition-all duration-500 bg-indigo-600 text-white shadow-md border-4 border-white ring-4 ring-indigo-100 scale-110";
        ind.innerHTML = stepNum;
        label.className = "msf-step-label text-xs font-bold text-indigo-600 mt-2 transition-colors duration-300 tracking-wide uppercase";
      } else {
        ind.className = "msf-step-indicator w-10 h-10 rounded-full flex items-center justify-center font-bold transition-all duration-500 bg-gray-200 text-gray-500 border-4 border-white";
        ind.innerHTML = stepNum;
        label.className = "msf-step-label text-xs font-medium text-gray-400 mt-2 transition-colors duration-300 tracking-wide uppercase";
      }
    });
    
    contents.forEach((content, index) => {
      const stepNum = index + 1;
      if (stepNum === currentStep) {
        content.className = "msf-step-content absolute w-full transition-all duration-500 transform translate-x-0 opacity-100 delay-100";
      } else if (stepNum < currentStep) {
        content.className = "msf-step-content absolute w-full transition-all duration-500 transform -translate-x-12 opacity-0 pointer-events-none";
      } else {
        content.className = "msf-step-content absolute w-full transition-all duration-500 transform translate-x-12 opacity-0 pointer-events-none";
      }
    });
    
    if (currentStep === 1) {
      btnPrev.className = "px-6 py-2.5 border border-gray-300 text-gray-700 font-bold rounded-xl transition-all duration-300 opacity-0 pointer-events-none absolute left-0";
    } else {
      btnPrev.className = "px-6 py-2.5 border border-gray-300 text-gray-700 font-bold rounded-xl hover:bg-gray-50 hover:text-indigo-600 focus:outline-none focus:ring-2 focus:ring-gray-200 transition-all duration-300 opacity-100 flex items-center justify-center gap-2";
    }
    
    if (currentStep === steps.length) {
      btnNext.innerHTML = `Submit <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>`;
      btnNext.className = "px-6 py-2.5 bg-emerald-500 text-white font-bold rounded-xl hover:bg-emerald-600 focus:outline-none focus:ring-2 focus:ring-emerald-400 focus:ring-offset-2 transition-all duration-300 ml-auto shadow-[0_4px_14px_0_rgba(16,185,129,0.39)] hover:shadow-[0_6px_20px_rgba(16,185,129,0.23)] hover:-translate-y-0.5 flex items-center justify-center gap-2 active:translate-y-0";
    } else {
      btnNext.innerHTML = `Next <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>`;
      btnNext.className = "px-6 py-2.5 bg-indigo-600 text-white font-bold rounded-xl hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-all duration-300 ml-auto shadow-[0_4px_14px_0_rgba(79,70,229,0.39)] hover:shadow-[0_6px_20px_rgba(79,70,229,0.23)] hover:-translate-y-0.5 flex items-center justify-center gap-2 active:translate-y-0";
    }
  }

  btnPrev.addEventListener('click', () => {
    if (currentStep > 1) {
      currentStep--;
      updateUI();
    }
  });
  
  btnNext.addEventListener('click', () => {
    if (currentStep < steps.length) {
      currentStep++;
      updateUI();
    } else {
      btnNext.innerHTML = `<svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>Submitting...`;
      setTimeout(() => {
        alert('Form submitted successfully!');
        currentStep = 1;
        updateUI();
      }, 1500);
    }
  });
  
  updateUI();
})();
</script>

Browser-Unterstützung

Funktioniert zuverlässig in den aktuellen Versionen aller modernen Browser (Chrome, Safari, Firefox, Edge). Es verwendet CSS-Transitions und Tailwind-Utility-Klassen für Animationen. JavaScript wird ausschließlich für das State-Management (Umschalten von Klassen und Berechnen der Fortschrittsbalken-Breite) eingesetzt, um eine optimale Performance zu gewährleisten.