SSCF - Einheitlicher Standard für Kontaktformulare

SSCF - Einheitlicher Standard für Kontaktformulare
Standards

38

15 min.

Definitionen

Der SSCF-Standard legt Anforderungen an die Semantik, Barrierefreiheit und Funktionslogik von Kontaktformularen fest.

Struktur und Semantik

Formularelement und Gruppierung von Feldern

  • Zum Erfassen und Übermitteln zusammengehöriger Daten wird das native Element form verwendet. Es stellt Formularsemantik, Tastaturverhalten und einen browserseitigen Übermittlungsmechanismus bereit.
  • Zusammengehörige Felder werden mit fieldset und legend gruppiert. fieldset wird nur verwendet, wenn die Felder eine sinnvolle logische Gruppe bilden; jedes einzelne Feld muss nicht separat umschlossen werden.
  • legend benennt die Gruppe und steht als erstes Kindelement in fieldset.
  • Für die Übermittlung mit POST werden method="post" explizit an form und die Adresse des Handlers über action festgelegt. Bei Formularen mit Dateien wird zusätzlich enctype="multipart/form-data" gesetzt.
  • Geheimnisse für Integrationen und Schlüssel externer Dienste gehören nicht in clientseitigen Code. Die Daten werden an einen geschützten serverseitigen Handler gesendet, der sie prüft und mit externen Systemen kommuniziert.

Bezeichnungen und Attribute von Formularelementen

  • Jedes zu übermittelnde Feld erhält eine eindeutige id und einen aussagekräftigen name. id verknüpft das Feld mit seiner Beschriftung; name bezeichnet das Feld im übermittelten Datensatz.
  • Für input wird ein passender type angegeben, zum Beispiel text, email, tel, checkbox, file, number oder range. select und textarea besitzen kein type-Attribut; die Interaktion wird durch das jeweilige Element bestimmt.
  • required wird nur für Felder verwendet, die im jeweiligen Ablauf tatsächlich erforderlich sind. Optionale Felder erhalten das Attribut nicht.
  • autocomplete wird mit passenden Tokens angegeben, zum Beispiel name, email, tel, given-name oder family-name. Dadurch kann der Browser gespeicherte Daten vorschlagen und den Zweck des Feldes erkennen.
  • placeholder ist optional. Er kann ein kurzes Formatbeispiel zeigen, ersetzt aber weder eine dauerhaft sichtbare label noch die einzige Erklärung eines Feldes.
  • Eine sichtbare label wird über übereinstimmende Werte von for und id mit dem Feld verknüpft oder umschließt das Feld. Durch Aktivieren der Beschriftung erhält das zugehörige Steuerelement den Fokus.

Beispiel für eine semantische Formularstruktur:

<form action="/de/contact" method="post" enctype="multipart/form-data" data-contact-form>
  <fieldset>
    <legend>Kontaktdaten</legend>

    <div class="form-field">
      <label for="name">Name</label>
      <input
        id="name"
        name="name"
        type="text"
        autocomplete="name"
        placeholder="Zum Beispiel Anna"
        required
      />
    </div>

    <div class="form-field">
      <label for="email">E-Mail-Adresse</label>
      <input
        id="email"
        name="email"
        type="email"
        autocomplete="email"
        placeholder="name@example.com"
        required
      />
    </div>

    <div class="form-field">
      <label for="message">Nachricht</label>
      <textarea
        id="message"
        name="message"
        placeholder="Die Frage kurz beschreiben"
        required
      ></textarea>
    </div>
  </fieldset>

  <div class="form-consent">
    <label class="form-consent__label">
      <input id="data-consent" name="dataConsent" type="checkbox" required />
      <span>Einwilligung zur Datenverarbeitung</span>
    </label>
    <a href="/de/policy" target="_blank" rel="noopener noreferrer">
      Bedingungen zur Datenverarbeitung (öffnet in einem neuen Tab)
    </a>
  </div>

  <button class="form-submit" type="submit">Absenden</button>
  <p role="status" aria-live="polite" data-form-status></p>
</form>

Das Kontrollkästchen und sein Beschriftungstext sind gemeinsam in label eingeschlossen. Dadurch schaltet auch ein Klick auf den Text das Feld um. Das Element a steht bewusst außerhalb des Labels und bleibt ein separates interaktives Element. Eine interne Seite sollte nur bei begründetem Bedarf in einem neuen Tab geöffnet werden; dieses Verhalten muss kenntlich sein. Bei target="_blank" wird rel="noopener noreferrer" gesetzt.

Feldzustände und Validierung

Visuelle Zustände

  • Der Standardzustand zeigt ein normales Feld ohne Fehler- oder Aktivierungsstil.
  • Der Fokuszustand hebt sich sichtbar ab und behält einen erkennbaren Indikator für die Tastaturnavigation.
  • Ein Fehler wird nicht nur durch Farbe vermittelt: Das Feld erhält eine Textmeldung und bei eigener programmatischer Validierung aria-invalid="true".
  • Die Fehlermeldung wird mit aria-describedby dem entsprechenden Feld zugeordnet. Sie benennt das Problem und die Korrekturmöglichkeit, zum Beispiel das erforderliche E-Mail-Format.
  • aria-invalid="true" wird erst gesetzt, wenn ein Fehler tatsächlich festgestellt wurde. Nach Korrektur des Werts wird der Zustand aktualisiert oder entfernt.
  • Ein Erfolgszustand muss nicht an jedem Feld angezeigt werden. Falls er dargestellt wird, wird seine Bedeutung zusätzlich durch Text oder ein weiteres Zeichen vermittelt, nicht nur durch einen grünen Rahmen.

Beispiel für ein Feld mit Fehlermeldung:

<div class="form-field form-field--error">
  <label for="email">E-Mail-Adresse</label>
  <input
    id="email"
    name="email"
    type="email"
    autocomplete="email"
    aria-invalid="true"
    aria-describedby="email-error"
    required
  />
  <p id="email-error">Eine E-Mail-Adresse in einem gültigen Format eingeben.</p>
</div>

Zeitpunkt der Prüfung und Deaktivierung der Übermittlung

  • Native HTML-Beschränkungen wie required, type="email", min, max und pattern werden verwendet, wenn sie zum jeweiligen Ablauf passen. Eigene Validierung ergänzt nur tatsächlich benötigte Regeln.
  • Die clientseitige Prüfung gibt unmittelbares Feedback; alle wichtigen Regeln werden jedoch serverseitig erneut geprüft, da Clientdaten verändert oder am Interface vorbei übermittelt werden können.
  • Fehler sollten nicht angezeigt werden, bevor das Feld verwendet, verlassen oder das Formular abgeschickt wurde. So erscheinen keine Fehlermeldungen für noch nicht bearbeitete Felder.
  • Einfache lokale Prüfungen erfolgen normalerweise bei der Eingabe, beim Verlassen des Feldes oder beim Absenden ohne zusätzliche Verzögerung. Ein Debounce von etwa 300 ms eignet sich für aufwendige oder netzwerkbasierte Prüfungen nach einer Eingabepause; er ersetzt weder die Prüfung bei Fokusverlust noch die Prüfung vor dem Absenden.
  • Die Absenden-Schaltfläche bleibt standardmäßig verfügbar, damit die Validierung gestartet und erklärt werden kann, was zu korrigieren ist. Eine Deaktivierung bei jedem ungültigen Wert kann den Grund verbergen und die Korrektur erschweren.
  • Wird die Schaltfläche projektbedingt deaktiviert, bis Bedingungen erfüllt sind, werden diese Bedingungen in der Nähe erklärt und Felder sowie Fehlermeldungen bleiben zugänglich. disabled ersetzt keine Fehlermeldung.
  • Bei einem Absendeversuch mit mehreren Fehlern wird eine verständliche Zusammenfassung oder eine Meldung am jeweiligen Feld angezeigt; bei Bedarf wird der Fokus zum ersten ungültigen Feld bewegt.

Safari und Autofill

  • In Safari auf dem iPhone wird die Schriftgröße direkt im fokussierten Formularelement auf mindestens 16px gesetzt, um automatisches Zoomen der Seite beim Fokussieren zu vermeiden.
  • Das Zoomen der Seite wird nicht durch Viewport-Beschränkungen deaktiviert. Die Vergrößerung über den Browser muss möglich bleiben.
  • Autofill wird nicht ohne konkreten Grund deaktiviert. Für personenbezogene Daten werden präzise autocomplete-Werte wie name, email und tel angegeben.
  • Falls der Systemstil für Autofill mit dem Design kollidiert, werden für :autofill und :-webkit-autofill kontrastreiche Text- und Hintergrundfarben festgelegt. Systemstile dürfen nicht auf Kosten lesbarer Inhalte oder des Fokusindikators verborgen werden.

Grundlegende Feld- und Autofill-Stile:

.form-field input,
.form-field select,
.form-field textarea,
.phone-field input {
  font-size: 16px;
}

.form-field input:focus-visible,
.form-field select:focus-visible,
.form-field textarea:focus-visible,
.phone-field input:focus-visible {
  outline: 2px solid #2457d6;
  outline-offset: 2px;
}

.form-field [aria-invalid="true"] {
  border-color: #b42318;
}

.form-field input:autofill,
.form-field input:-webkit-autofill,
.phone-field input:autofill,
.phone-field input:-webkit-autofill {
  -webkit-text-fill-color: #161616;
  box-shadow: 0 0 0 1000px #fff inset;
}

Die Farben im Beispiel werden durch geprüfte Design-Tokens ersetzt. 16px bezieht sich auf den Text im Eingabefeld; die Größe der Beschriftung oder des Platzhalters ändert nicht die Schriftgröße des Feldtexts.

Feldtypen und mobile Eingabe

Telefonnummer

  • Für Telefonnummern wird type="tel" mit autocomplete="tel" verwendet. inputmode="tel" kann mobilen Geräten zusätzlich eine passende Bildschirmtastatur vorschlagen.
  • Internationale Telefonnummern haben keine einheitliche feste Ziffernlänge. Prüfungen auf „mindestens 11 Ziffern“ oder „genau 11 Ziffern“ sind für unterschiedliche Länder und Formate ungeeignet.
  • Eine Nummer wird anhand des Nummerierungsplans des ausgewählten Landes geprüft und für die Übertragung in ein vereinbartes Format wie E.164 normalisiert. Eine Maske steuert die Darstellung, bestätigt aber weder die Existenz noch die Erreichbarkeit einer Nummer.
  • Wiederholte Ziffern allein sind kein zuverlässiges Merkmal einer ungültigen Nummer. Solche Heuristiken werden nicht als allgemeines Eingabeverbot verwendet; Spamschutz wird separat serverseitig umgesetzt.
  • Beim Wechsel des Landes werden Vorwahl und Anzeigeformat aktualisiert. Die Eingabe oder das Einfügen einer internationalen Nummer darf keine Ziffern verlieren oder die Landesvorwahl doppelt hinzufügen.
  • Das Zeichen + und Ziffern der Landesvorwahl werden nicht allgemein für die manuelle Eingabe gesperrt: Internationale Nummern können eingetippt oder eingefügt werden. Ist die Vorwahl des ausgewählten Landes fest, wird eine doppelte Vorwahl normalisiert statt angehängt.
  • Ist die ausgewählte Landesvorwahl nicht editierbar, steht der Cursor beim Fokussieren direkt dahinter. Gleichzeitig bleiben Markieren und Ersetzen der Nummer, das Einfügen einer internationalen Nummer und der Länderwechsel möglich. Gemeint ist die Cursorposition beim Fokussieren, nicht das automatische Setzen von autofocus beim Laden des Formulars. Für Russland sind die nationale Vorwahl 8 und die internationale Vorwahl +7 keine austauschbaren Masken; die Eingabe wird in das ausgewählte Format normalisiert.
  • Das Anfangsland kann aus Benutzereinstellungen, der Website-Locale oder einer ausdrücklichen Auswahl stammen. IP-basierte Erkennung erfordert einen separaten Dienst, kann ungenau sein und darf weder die manuelle Länderauswahl noch die Nummerneingabe verhindern.
  • Die erwartete Cursorposition bleibt beim Tippen, Einfügen, Markieren und Löschen innerhalb der Nummer erhalten. Die Cursorposition sollte nicht nach jedem Eingabeereignis manuell verschoben werden, wenn die Bibliothek die Formatierung bereits verwaltet.
  • Eine eingegebene Telefonnummer bestätigt nicht die Inhaberschaft. Für die Prüfung der Erreichbarkeit oder Inhaberschaft ist ein eigener Schritt erforderlich, zum Beispiel ein Bestätigungscode.

React-Implementierung des Projekts

Im React-Projekt wird für internationale Telefonnummern react-international-phone anstelle von @react-input/mask verwendet. Das Beispiel useMask({ mask, replacement }) gehört zu @react-input/mask und ist nicht die API der Telefonbibliothek. Dafür kommt PhoneInput zum Einsatz; die Komponente formatiert Nummern, unterstützt die Länderauswahl und verwaltet die Cursorposition. Eine IP-basierte Ländererkennung ist keine integrierte Funktion der Bibliothek und ersetzt weder Nummernvalidierung noch die Auswahl durch die Nutzenden.

import { useState } from 'react';
import { PhoneInput } from 'react-international-phone';
import 'react-international-phone/style.css';

export const PhoneField = () => {
  const [phone, setPhone] = useState('');

  return (
    <div className="phone-field">
      <label htmlFor="phone">Telefon</label>
      <PhoneInput
        defaultCountry="ru"
        forceDialCode
        value={phone}
        onChange={(phone) => setPhone(phone)}
        inputProps={{
          id: 'phone',
          name: 'phone',
          type: 'tel',
          autoComplete: 'tel',
          inputMode: 'tel',
          required: true,
        }}
      />
    </div>
  );
};

react-international-phone übernimmt Eingabe und Formatierung, wird in der aktuellen Dokumentation jedoch nicht mehr als Bibliothek zur Telefonnummernvalidierung geführt. Für die Prüfung anhand von Nummerierungsplänen wird eine spezialisierte Bibliothek wie google-libphonenumber sowie eine serverseitige Prüfung verwendet.

import { PhoneNumberUtil } from 'google-libphonenumber';

const phoneUtil = PhoneNumberUtil.getInstance();

const isValidPhone = (phone) => {
  try {
    return phoneUtil.isValidNumber(phoneUtil.parseAndKeepRawInput(phone));
  } catch (error) {
    return false;
  }
};

Die Prüfung von Format und Nummerierungsplan bestätigt nicht, dass eine Nummer aktiv ist oder der absendenden Person gehört.

Select, Textarea und Datei-Uploads

  • Für Auswahllisten wird standardmäßig ein natives <select> verwendet. Es bietet integrierte Tastatur- und Plattformunterstützung.
  • Eine eigene Liste wird nur verwendet, wenn ein natives <select> eine tatsächliche Anforderung nicht erfüllt. Zugänglicher Name, geöffneter und ausgewählter Zustand, Tastaturbedienung und vorhersehbares Fokusmanagement werden nach dem passenden ARIA-Muster umgesetzt.
  • Die Größenänderung eines <textarea> bleibt möglich, sofern sie das Layout nicht beeinträchtigt. Muss die vertikale Größenänderung begrenzt werden, eignen sich resize: vertical oder eine andere begründete Begrenzung; ein pauschales resize: none kann die Eingabe längerer Texte erschweren.
  • Zulässige Dateitypen, maximale Größe und Anzahl der Dateien werden festgelegt. Das Attribut accept schlägt lediglich Dateien im Dateiauswahldialog vor und ist keine Sicherheitsprüfung.
  • Dateityp und -größe werden auf dem Server erneut geprüft. Ein MIME-Header oder Dateiname allein ist nicht vertrauenswürdig; zulässige Erweiterungen werden beschränkt und Dateinamen sowie Speicherung sicher behandelt.
  • Nach der Auswahl wird eine Liste der Anhänge mit Name und Größe angezeigt. Bei Bedarf werden Upload-Fortschritt, Fehler und eine Möglichkeit zum Entfernen einzelner Dateien ergänzt.

Bereichsschieberegler

  • Für die Auswahl eines Werts innerhalb eines Bereichs wird ein natives <input type="range"> verwendet, sofern dessen Verhalten zur Aufgabe passt. Semantik, Fokus, Tastaturbedienung und Zeigereingabe sind bereits integriert.
  • Wenn ein exakter Wert wichtig ist, kann ein zugehöriges Feld type="number" ergänzt werden. Bereich, Schrittweite und aktueller Wert werden aus einer gemeinsamen Zustandsquelle synchronisiert.
  • Für die Kombination „Schieberegler + Zahlenfeld“ wird ein kanonischer Wert übermittelt. Derselbe Parameter wird nicht versehentlich doppelt in die Formulardaten aufgenommen.
  • Der Schieberegler erhält eine zugängliche Beschriftung sowie sinnvolle Werte für min, max, step und das anfängliche value. Der aktuelle Wert wird zusätzlich als Text angezeigt, wenn die Position allein nicht verständlich genug ist.
  • Ein nativer Schieberegler unterstützt Tastatur und Zeiger. Bei einer eigenen Komponente müssen Zeiger, Touch, Tastatur, Fokus, zugänglicher Name und Wertübermittlung an Hilfstechnologien separat implementiert werden.
  • cursor: pointer kann die Interaktivität anzeigen. cursor: grab und cursor: grabbing werden nur eingesetzt, wenn die Komponente tatsächlich Ziehen unterstützt; der Cursor ersetzt weder Touch- noch Tastaturbedienung.
  • Ein nativer Regler verarbeitet Klicks auf der Schiene entsprechend der Browserimplementierung. Ein eigener Regler muss sowohl mit Maus als auch Touch zum gewählten Punkt springen können, ohne das Seitenscrollen zu stören.

Beispiel für ein gekoppeltes Zahlenfeld und einen Schieberegler:

<div class="form-field">
  <label for="budget-range">Budget</label>
  <input
    id="budget-range"
    type="range"
    min="0"
    max="100000"
    step="5000"
    value="50000"
    aria-describedby="budget-current-value"
  />
  <output id="budget-current-value" for="budget-range">50.000 EUR</output>

  <label for="budget-value">Genauer Betrag, EUR</label>
  <input
    id="budget-value"
    name="budget"
    type="number"
    min="0"
    max="100000"
    step="5000"
    value="50000"
    inputmode="numeric"
    required
  />
</div>

Beide Steuerelemente aktualisieren denselben Wert im Interface. In diesem Beispiel besitzt nur das Zahlenfeld ein name, sodass der Wert einmal übermittelt wird.

Beispiel für die Synchronisierung nativer Felder:

const rangeInput = document.querySelector('#budget-range');
const numberInput = document.querySelector('#budget-value');
const budgetOutput = document.querySelector('#budget-current-value');

const formatBudget = (value) => new Intl.NumberFormat('de-DE').format(Number(value)) + ' EUR';

const updateBudgetOutput = () => {
  budgetOutput.value = formatBudget(rangeInput.value);
};

rangeInput.addEventListener('input', () => {
  numberInput.value = rangeInput.value;
  updateBudgetOutput();
});

numberInput.addEventListener('change', () => {
  if (!numberInput.validity.valid) return;

  rangeInput.value = numberInput.value;
  numberInput.value = rangeInput.value;
  updateBudgetOutput();
});

Der Schieberegler aktualisiert das Zahlenfeld während der Bewegung. Eine eingegebene Zahl wird nach Abschluss der Eingabe und nur dann mit dem Schieberegler synchronisiert, wenn sie die Beschränkungen min, max und step erfüllt.

input[type="range"] {
  cursor: pointer;
}

input[type="range"]:active {
  cursor: grabbing;
}

Barrierefreiheit und Tastaturbedienung

  • Alle Formularelemente sind in vorhersehbarer Reihenfolge mit Tab und Shift+Tab erreichbar; der sichtbare Fokusindikator wird nicht entfernt.
  • Ein natives <select> folgt den Tastaturkonventionen des Betriebssystems und Browsers. Eine eigene Liste muss ein konsistentes Tastaturmodell einschließlich Navigation und Auswahl implementieren.
  • Ein fokussiertes Kontrollkästchen wird mit Leertaste umgeschaltet. Das native Element vermittelt seinen Zustand bereits und benötigt keine doppelten ARIA-Attribute.
  • Jedes Feld benötigt einen zugänglichen Namen, normalerweise durch <label>. aria-label oder aria-labelledby werden nur verwendet, wenn keine sichtbare Beschriftung vorhanden oder diese nicht ausreichend ist.
  • ARIA ergänzt fehlende Namen, Zustände oder Beziehungen und wird nicht pauschal jedem Input und Button hinzugefügt. Native Semantik ist einer wiederholten Rollenangabe vorzuziehen.
  • Fehler müssen mehr als nur durch Farbe erkennbar sein. Die Meldung bleibt sichtbar und wird programmatisch mit dem Feld verknüpft; Änderungen am Formular werden bei Bedarf angekündigt, ohne den Fokus unerwartet zu verschieben.
  • Der Buttontext liefert normalerweise den zugänglichen Namen. Buttons, die nur ein Symbol enthalten, erhalten über aria-label oder aria-labelledby einen verständlichen Namen.
  • Ein Kontrollkästchen kann zusammen mit seinem Beschriftungstext in <label> eingeschlossen werden, sodass der gesamte Text das Feld umschaltet. Ein Richtlinienlink steht außerhalb des Labels, damit kein interaktiver Link darin verschachtelt wird.
  • Ob ein Kontrollkästchen verpflichtend ist, hängt vom Formularablauf und den Produktanforderungen ab; ein Link zu einer Richtlinie allein macht nicht jede Einwilligung verpflichtend.
  • Fehler- und Erfolgsmeldungen sind kurz, verständlich und leicht auffindbar. Für dynamische Statusmeldungen eignet sich ein separater Bereich mit role="status" und aria-live="polite".

Übermittlung und Ergebniszustände

Übermittlungszustände

  • Vor dem Absenden enthält der Button eine klare Handlungsbeschriftung, zum Beispiel „Absenden“.
  • Während einer Netzwerkanfrage wird eine erneute Übermittlung verhindert. Der Button kann vorübergehend disabled erhalten; der Formularzustand kann mit aria-busy="true" vermittelt werden.
  • Der Status des Vorgangs wird getrennt vom Button angezeigt, zum Beispiel in einem Bereich mit role="status". Änderungen des Textes in einem deaktivierten Button werden von Hilfstechnologien nicht immer zuverlässig angekündigt.
  • Nach bestätigtem Erfolg erscheint eine Meldung wie „Formular wurde gesendet“. Das Formular wird erst nach der Bestätigung des Servers zurückgesetzt; bei einem Fehler bleiben die eingegebenen Werte erhalten, sofern keine Löschung angefordert wurde.
  • Die Erfolgsmeldung wird nicht nach willkürlichen fünf Sekunden automatisch ausgeblendet. Falls die Beschriftung des Buttons zeitgesteuert zurückgesetzt wird, bleibt die Meldung lange genug lesbar.
  • Das automatische Ausblenden einer Statusmeldung ist kein Spamschutz. Ratenbegrenzung, Schutz vor doppelten Anfragen und Missbrauchsprüfungen gehören auf den Server.

Ist der Button tatsächlich deaktiviert, muss sich sein visueller Zustand klar unterscheiden. Cursor und Transparenz sind nur visuelle Hinweise; der Grund für die nicht mögliche Übermittlung muss weiterhin textlich verständlich sein.

.form-submit:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

Serverseitige Verarbeitung und Integrationen

  • Vor der Übermittlung werden alle Felder clientseitig geprüft; dieselben wichtigen Regeln werden serverseitig wiederholt. Der Server vertraut weder Validierungsflags noch disabled-Werten oder Einschränkungen des Interfaces.
  • Daten werden per POST über HTTPS gesendet. CSRF-Schutz, Ratenbegrenzung, Idempotenz und weitere Maßnahmen richten sich nach dem Bedrohungsmodell und der Authentifizierung des Handlers.
  • Müssen Daten an mehrere Systeme übermittelt werden, sendet der Browser sie an einen eigenen serverseitigen Handler. Schlüssel für Bitrix, Directus, Telegram oder andere Integrationen gehören nicht in das JavaScript der Seite.
  • Promise.allSettled() meldet die Ergebnisse mehrerer unabhängiger Promises, macht sie aber weder zu einer atomaren Transaktion noch macht es bereits ausgeführte Aktionen bei einem Teilausfall rückgängig. Der Server legt fest, was als angenommen gilt, wie fehlgeschlagene Zustellungen wiederholt und Duplikate verhindert werden.
  • Den Nutzenden wird das Ergebnis der Hauptaktion mitgeteilt. Erfolg wird erst angezeigt, wenn der Server das festgelegte Annahmekriterium bestätigt hat, etwa das Speichern der Anfrage oder ihre zuverlässige Aufnahme in eine Warteschlange.
  • Bei einem Fehler wird der nächste Schritt erklärt, ohne die eingegebenen Werte zu löschen. Vom Server zurückgegebene Feldfehler werden den jeweiligen Steuerelementen zugeordnet.

Beispiel für die Übermittlung an einen serverseitigen Handler:

const form = document.querySelector('[data-contact-form]');
const submitButton = form.querySelector('[type="submit"]');
const formStatus = form.querySelector('[data-form-status]');
let isSubmitting = false;

form.addEventListener('submit', (event) => {
  event.preventDefault();

  if (isSubmitting || !form.reportValidity()) return;

  isSubmitting = true;
  submitButton.disabled = true;
  form.setAttribute('aria-busy', 'true');
  formStatus.textContent = 'Wird gesendet…';

  fetch(form.action, {
    method: 'POST',
    body: new FormData(form),
    headers: { Accept: 'application/json' },
  })
    .then((response) => {
      if (!response.ok) throw new Error('Form submission failed');

      form.reset();
      formStatus.textContent = 'Das Formular wurde erfolgreich gesendet.';
    })
    .catch(() => {
      formStatus.textContent = 'Das Formular konnte nicht gesendet werden. Verbindung prüfen und erneut versuchen.';
    })
    .then(() => {
      isSubmitting = false;
      submitButton.disabled = false;
      form.removeAttribute('aria-busy');
    });
});

Das Beispiel setzt data-contact-form, einen Absende-Button und einen Statusbereich im Markup voraus. In einer produktiven Implementierung werden außerdem Serverfehler, Zeitüberschreitungen und Wiederholungen behandelt; clientseitiger Code kommuniziert nicht direkt mit externen Integrationen.

Prüfung

  • Die korrekte Struktur mit <form> wird geprüft; <fieldset> und <legend> gruppieren nur zusammengehörige Felder.
  • Jedes Feld besitzt eine dauerhafte Beschriftung, eine eindeutige id, einen passenden type, soweit anwendbar, und einen name, wenn sein Wert übermittelt werden soll.
  • Native required-Beschränkungen, Feldformate, autocomplete und die Abgrenzung zwischen Beschriftung und optionalem placeholder werden geprüft.
  • Standard-, Fokus- und Fehlerzustände sind unterscheidbar; Fehler werden nicht nur durch Farbe vermittelt und mit erklärendem Text verknüpft.
  • Fehler erscheinen nicht grundlos vor der Interaktion; die Validierung erfolgt zu passenden Zeitpunkten und erneut beim Absenden.
  • Es ist verständlich, warum die Übermittlung nicht fortgesetzt wurde. Ein deaktivierter Button ist nicht der einzige Hinweis auf einen Fehler oder eine erforderliche Aktion.
  • Maus-, Touch- und Tastaturbedienung werden geprüft, einschließlich Tab, Shift+Tab, Leertaste für Kontrollkästchen sowie Tastaturverhalten nativer und eigener Auswahllisten.
  • Auf dem iPhone wird geprüft, dass ein Feld beim Fokussieren die Seite nicht automatisch vergrößert und Touch-Geräte eine geeignete Tastatur anzeigen.
  • Autofill-Werte behalten lesbaren Text, ausreichenden Kontrast, Fokus und einen sichtbaren Feldzustand.
  • Telefonnummern werden für das ausgewählte Land und internationale Formate getestet, einschließlich Einfügen, Löschen, Cursorbewegung, Länderwechsel und Nummern mit wiederholten Ziffern.
  • Eine IP-basierte Ländererkennung wird gegebenenfalls als ungefähres Anfangsland mit manueller Auswahl und funktionierendem Fallback getestet.
  • Eigene Auswahllisten, der Länderauswahlschalter des Telefonfelds und eigene Schieberegler werden mit Tastatur und Hilfstechnologien geprüft.
  • Bei Dateien werden zulässige Typen, Größe, Anzahl, Listenanzeige, Entfernen, serverseitige Prüfung und Uploadfehler getestet.
  • Zahlenfeld und Schieberegler bleiben bei Eingabe, Ziehen, Grenzwerten und Schrittweiten synchron; der Wert wird im vereinbarten Format übermittelt.
  • Bei der Übermittlung werden Mehrfachaktivierung, Netzwerk- und Serverfehler, Werterhalt bei Fehlern, Zurücksetzen nach Erfolg und Statusmeldungen geprüft.
  • Löst die Übermittlung mehrere Integrationen aus, werden Teilausfälle und duplikatfreie Wiederholungen getestet.

SSCF-Checkliste

KategorieHauptanforderungenZweck
Semantik<form>, <fieldset>, <legend>, label, passende SteuerelementtypenVerständliche Struktur und natives Verhalten
DatenEindeutige id-Werte, name für übermittelte Werte, required je nach AblaufKorrekte Übermittlung der Felder
AutofillPräzise autocomplete-Tokens; Placeholder nur als HinweisSchnelleres und verständlicheres Ausfüllen
ValidierungClientseitiges Feedback und erneute serverseitige PrüfungFehler finden, ohne dem Client zu vertrauen
ZuständeStandard, Fokus, Fehler, Laden und Ergebnis; nicht nur FarbeAktuellen Formularzustand verständlich machen
TelefonLänderbezogene Formatierung, Normalisierung, separate GültigkeitsprüfungNationale und internationale Nummern unterstützen
Spezielle FelderNatives Select und Range, zugängliches Textarea, servergeprüfte DateienVorhersehbare Dateneingabe
BarrierefreiheitBeschriftungen, Fehlerverknüpfungen, Tastatur, passende ARIA-SemantikFormular auf unterschiedliche Weise bedienbar und verständlich machen
ÜbermittlungPOST an den Server, geschützte Integrationen, Behandlung von TeilausfällenZuverlässige Übermittlung und verständliche Ergebnisse

Ähnliche Kategorien:

Ähnliche Artikel

  • Aufbau einer React-Komponente

    Meine Vorstellung davon, wie jede React-Komponente aussehen sollte

    421

    8 min.

  • SST - Einheitlicher Standard für Registerkarten

    Der SST-Standard legt Anforderungen an die Semantik, Barrierefreiheit und Funktionslogik von Registerkarten fest

    62

    6 min.

  • SSF-U – Einheitlicher Standard für Vollbildmodus

    Der SSF-U-Standard legt Anforderungen an die Semantik, Barrierefreiheit und Funktionslogik von Vollbildmodus fest

    248

    2 min.

  • SSA – Einheitlicher Standard für Akkordeons

    Der SSA-Standard legt Anforderungen an die Semantik, Barrierefreiheit und Funktionslogik von Akkordeons fest

    258

    2 min.

  • Bad Practices für Websites

    Analyse kritischer Fehler im Webdesign. Warum Slider, Autoplay und schwerfällige Seiten die Konversionsrate sowie die Platzierungen bei Google verschlechtern

    232

    2 min.

  • SSP - Einheitlicher Standard für Paginierung

    Der SSP-Standard legt Anforderungen an die Semantik, Barrierefreiheit und Funktionslogik von Paginierung fest

    240

    1 min.

  • Alle Artikel

Kontaktieren Sie mich