HTML Formulare
Formulare sind das Bindeglied zwischen Nutzer*innen und Website - sie sammeln Informationen, schicken Daten ab und ermöglichen Interaktion. Code mit HTML5-Strukturelementen, der für Menschen, Suchmaschinen und Screenreader gleichermaßen verständlich ist.
Grundaufbau eines Formulars
Ein Formular beginnt immer mit dem <form>-Element. Darin
befinden sich die Eingabefelder und Schaltflächen, die der Browser dann an den angegebenen
Server oder eine andere Zieladresse sendet.
<form action="/formular-verarbeiten" method="post">
<label for="name">Name:</label>
<input type="text" id="name" name="name">
<button type="submit">Absenden</button>
</form>
Form-Attribute
Die Attribute action und method
steuern, wohin die
Formulardaten
geschickt werden und wie:
action= Zieladresse, z. B. eine Datei oder URLmethod="get"= Daten in der URL (sichtbar)method="post"= Daten im Request-Body (unsichtbar, sicherer)
Neben action und method gibt
es
weitere nützliche Attribute:
enctype- Für Datei-Uploads:"multipart/form-data"novalidate- Schaltet Browser-Validierung ausautocomplete="off"- Deaktiviert Auto-Vervollständigungtarget="_blank"- Öffnet Ergebnis in neuem Tab
<!-- Formular mit Datei-Upload -->
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="dokument">
<button type="submit">Hochladen</button>
</form>
Formular-Attribute erklärt - for,
id,
name & type
Wenn du dir Formular-Code anschaust, siehst du viele verschiedene Attribute, die auf den ersten Blick verwirrend wirken können:
<label for="name">Name:</label>
<input type="text" id="name" name="name" class="form-input">
Hier sehen wir for, type, id, name und
class - das sind alles HTML-Attribute (keine
CSS-Klassen!), und
jedes hat eine eigene, wichtige Funktion:
Die meisten Attribute in Formularen haben nichts mit Styling zu tun, sondern steuern das Verhalten und die Funktion der Felder.
Die wichtigsten Attribute und ihre Funktionen
| Attribut | Wo? | Funktion | Beispiel |
|---|---|---|---|
for |
<label> |
Verbindet das Label mit einem Input-Feld (muss mit id
übereinstimmen)
|
<label for="email"> |
id |
<input> |
Eindeutige ID für das Element (wichtig für Labels und CSS/JS) | <input id="email"> |
name |
<input> |
Der Name, unter dem die Daten ans Backend gesendet werden | <input name="user_email"> |
type |
<input> |
Bestimmt die Art des Eingabefelds (Text, E-Mail, Passwort...) | <input type="email"> |
class |
Überall | CSS-Klasse(n) für Styling | <input class="form-input"> |
Warum brauchen wir alle diese Attribute?
Beispiel ohne eindeutige Namen:
<!-- Schlecht: alles heißt gleich -->
<label for="name">Name:</label>
<input type="text"
id="name"
name="name">
Problem: Wenn du mehrere Formulare hast, gibt's Konflikte - IDs müssen auf der ganzen Seite eindeutig sein!
Besser mit eindeutigen Namen:
<!-- Gut: eindeutige Namen -->
<label for="contact-name">Name:</label>
<input type="text"
id="contact-name"
name="user_name">
Vorteil: id ist eindeutig, name ist sprechend
für die Datenbank.
Praktisches Beispiel: Alle Attribute im Einsatz
<form action="/register" method="post">
<!-- Label verbindet sich mit Input über for/id -->
<label for="register-email">E-Mail-Adresse</label>
<input
type="email" <!-- Art des Felds: E-Mail mit Validierung -->
id="register-email" <!-- Eindeutige ID für Label und CSS/JS -->
name="user_email" <!-- Name für Backend/Datenbank -->
class="form-input" <!-- CSS-Klasse für Styling -->
placeholder="deine@email.de" <!-- Hinweistext -->
required> <!-- Pflichtfeld -->
</form>
Was passiert hier?
type="email"→ Browser validiert, ob eine E-Mail eingegeben wurdeid="register-email"→ Verbindet sich mit<label for="register-email">name="user_email"→ Wenn du das Formular abschickst, kommt am Server an:user_email=deine@email.declass="form-input"→ Nur für CSS-Styling
id→ sprechend und eindeutig:contact-form-email,newsletter-signup-namename→ Backend-freundlich:user_email,customer_name(oft mit Unterstrichen)class→ wiederverwendbar:form-input,btn-primary
Eingabefelder (Text-basiert)
Das wichtigste Formular-Element ist <input>. Je nach
type ändert sich das Verhalten und die Darstellung. Hier sind
die
textbasierten
Typen:
| Typ | Beschreibung | Beispiel |
|---|---|---|
text |
Einzeiliges Texteingabefeld | <input type="text"> |
email |
Validiert E-Mail-Format | <input type="email"> |
password |
Versteckt eingegebenen Text | <input type="password"> |
tel |
Telefonnummer (zeigt Zifferntastatur auf Mobilgeräten) | <input type="tel"> |
url |
Validiert URL-Format | <input type="url"> |
search |
Suchfeld (oft mit Lösch-Button) | <input type="search"> |
Eingabefelder (Zahlen & Datum)
Diese Typen bieten spezielle UI-Elemente für Zahlen und Zeitangaben:
| Typ | Beschreibung | Beispiel |
|---|---|---|
number |
Nur Zahlen, mit Spinner-Buttons | <input type="number" min="0" max="100"> |
range |
Schieberegler | <input type="range" min="0" max="100"> |
date |
Datumsauswahl | <input type="date"> |
time |
Zeitauswahl | <input type="time"> |
datetime-local |
Datum und Uhrzeit kombiniert | <input type="datetime-local"> |
month |
Monat und Jahr | <input type="month"> |
week |
Kalenderwoche | <input type="week"> |
Eingabefelder (Auswahl & Sonstige)
Diese Typen dienen zur Auswahl oder haben spezielle Funktionen:
| Typ | Beschreibung | Beispiel |
|---|---|---|
checkbox |
Ankreuzfeld (mehrere wählbar) | <input type="checkbox"> |
radio |
Auswahl (nur eine Option) | <input type="radio" name="gruppe"> |
color |
Farbauswahl-Dialog | <input type="color"> |
file |
Datei-Upload | <input type="file"> |
hidden |
Unsichtbares Feld (für technische Daten) | <input type="hidden" name="token" value="abc123">(nicht sichtbar) |
Wichtige Input-Attribute
Diese Attribute erweitern die Funktionalität von Eingabefeldern:
| Attribut | Beschreibung |
|---|---|
placeholder |
Grauer Hinweistext, verschwindet bei Eingabe |
value |
Vorbelegter Wert im Feld |
name |
Name für die Datenübertragung (wichtig für Backend!) |
id |
Eindeutige ID (für Labels und CSS) |
required |
Pflichtfeld |
disabled |
Feld ist deaktiviert (nicht bearbeitbar, wird nicht gesendet) |
readonly |
Feld ist schreibgeschützt (wird aber gesendet) |
autofocus |
Setzt den Cursor automatisch in dieses Feld |
autocomplete |
Steuert Browser-Autovervollständigung (on/off) |
<!-- Beispiel mit verschiedenen Attributen -->
<input type="email"
id="email"
name="email"
placeholder="[email protected]"
required
autofocus
autocomplete="email">
<!-- Schreibgeschütztes Feld mit Wert -->
<input type="text"
value="Dieser Wert ist fest"
readonly>
<!-- Deaktiviertes Feld -->
<input type="text"
value="Nicht verfügbar"
disabled>
Demo Browser-Default:
Demo mit CSS gestyled:
CSS anzeigen
/* Demo Container */
.demo-styled {
padding: 1.5rem;
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 8px;
margin: 1rem 0;
}
/* Labels */
.demo-styled label {
display: block;
margin-bottom: 0.5rem;
color: var(--text-primary);
font-weight: 500;
}
/* Input-Felder */
.demo-styled input[type="text"],
.demo-styled input[type="email"],
.demo-styled input[type="password"] {
width: 100%;
padding: 0.75rem 1rem;
background: var(--bg-primary);
border: 1px solid var(--border-color);
border-radius: 6px;
color: var(--text-primary);
font-size: 1rem;
margin-bottom: 1rem;
transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
/* Focus-Status */
.demo-styled input:focus {
outline: none;
border-color: var(--accent-blue-hover);
}
/* Placeholder */
.demo-styled input::placeholder {
color: var(--text-muted);
}
/* Disabled Inputs ausgrauen */
.demo-styled input:disabled,
.demo-styled input[disabled] {
color: var(--text-muted);
background: var(--bg-primary);
opacity: 0.6;
cursor: not-allowed;
}
Dropdowns & Textbereiche
Für Auswahlmenüs und mehrzeilige Eingaben gibt es eigene Tags:
<!-- Dropdown/Select -->
<label for="land">Land:</label>
<select id="land" name="land">
<option value="">Bitte wählen...</option>
<option value="de">Deutschland</option>
<option value="at">Österreich</option>
<option value="ch">Schweiz</option>
</select>
<!-- Textarea für lange Texte -->
<label for="nachricht">Nachricht:</label>
<textarea id="nachricht" name="nachricht" rows="5" cols="40"></textarea>
Demo Browser-Default:
Demo mit CSS gestyled:
CSS anzeigen
/* Select & Textarea */
.demo-styled select,
.demo-styled textarea {
width: 100%;
padding: 0.75rem 1rem;
background: var(--bg-primary);
border: 1px solid var(--border-color);
border-radius: 6px;
color: var(--text-primary);
font-size: 1rem;
margin-bottom: 1rem;
transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.demo-styled select:focus,
.demo-styled textarea:focus {
outline: none;
border-color: var(--accent-blue-hover);
}
.demo-styled textarea::placeholder {
color: var(--text-muted);
}
Optgroup - Optionen gruppieren
Mit <optgroup> kannst du Dropdown-Optionen in Kategorien
unterteilen:
<select name="fahrzeug">
<optgroup label="Autos">
<option value="vw">VW</option>
<option value="bmw">BMW</option>
</optgroup>
<optgroup label="Motorräder">
<option value="honda">Honda</option>
<option value="yamaha">Yamaha</option>
</optgroup>
</select>
Demo Browser-Default:
Demo mit CSS gestyled:
Das Styling von <optgroup> und
<option> im Dropdown ist
stark browserspezifisch begrenzt. Die meisten Browser rendern das Dropdown nativ und
ignorieren
viele CSS-Eigenschaften.
Die größten Unterschiede sieht man am Select-Feld selbst (Padding, Border,
Border-Radius, Focus-State).
CSS anzeigen
/* Select Dropdown */
.demo-styled select {
width: 100%;
padding: 0.75rem 1rem;
background: var(--color-bg-darker, #0f0f1a);
border: 1px solid var(--color-border, #3d3d5c);
border-radius: 6px;
color: var(--color-text, #e0e0e0);
font-size: 1rem;
transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.demo-styled select:focus {
outline: none;
border-color: var(--color-accent, #6c9bd1);
box-shadow: 0 0 0 3px rgba(108, 155, 209, 0.2);
}
/* Optgroup Labels (Gruppierungen) */
.demo-styled optgroup {
font-weight: 600;
color: var(--color-accent, #6c9bd1);
font-style: normal;
}
/* Optionen innerhalb der Gruppen */
.demo-styled option {
padding: 0.5rem;
background: var(--color-bg-darker, #0f0f1a);
color: var(--color-text, #e0e0e0);
}
Datalist - Auto-Vervollständigung
Das <datalist>-Element bietet Vorschläge während der
Eingabe -
die Nutzer*innen können aber auch eigene Werte eingeben:
<label for="browser">Browser:</label>
<input list="browsers" id="browser" name="browser" placeholder="Bitte auswählen...">
<datalist id="browsers">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
<option value="Edge">
<option value="Opera">
</datalist>
Demo Browser-Default:
Demo mit CSS gestyled:
Bei <datalist> kann man leider nur das
Input-Feld
selbst stylen, nicht das aufklappende Dropdown (das rendert der Browser nativ).
CSS anzeigen
/* Input mit Datalist */
.demo-styled input[list] {
width: 100%;
padding: 0.75rem 1rem;
background: var(--bg-primary);
border: 1px solid var(--border-color);
border-radius: 6px;
color: var(--text-primary);
font-size: 1rem;
font-family: inherit;
transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.demo-styled input[list]:focus {
outline: none;
border-color: var(--accent-blue-light);
box-shadow: 0 0 0 3px rgba(108, 155, 209, 0.2);
background: var(--bg-secondary);
}
.demo-styled input[list]::placeholder {
color: var(--text-muted);
}
Der Unterschied zu <select>: Bei <datalist> sind die
Optionen nur Vorschläge - Nutzer*innen können auch andere Werte eingeben.
Output, Progress & Meter
Diese HTML5-Elemente zeigen berechnete Werte oder Fortschritt an:
| Element | Beschreibung | Beispiel |
|---|---|---|
<output> |
Zeigt Berechnungsergebnis an | |
<progress> |
Fortschrittsbalken (Ladevorgang) | |
<meter> |
Messwert in bekanntem Bereich |
<!-- Output für Berechnungen -->
<form oninput="result.value = parseInt(a.value) + parseInt(b.value)">
<input type="number" id="a" value="10"> +
<input type="number" id="b" value="20"> =
<output name="result" for="a b">30</output>
</form>
<!-- Progress: Fortschritt (0 bis max) -->
<label for="download">Download-Fortschritt:</label>
<progress id="download" value="70" max="100">70%</progress>
<!-- Meter: Messwert mit Schwellenwerten -->
<label for="disk">Speicherplatz:</label>
<meter id="disk" value="0.7" min="0" max="1"
low="0.3" high="0.8" optimum="0.5">70%</meter>
<progress> ist für Vorgänge (Laden, Upload), <meter> für statische Messungen (Speicher, Akku,
Bewertungen). Meter hat zusätzlich low, high und optimum für farbliche
Hervorhebung.
Fieldset & Legend - Felder gruppieren
Mit <fieldset> und <legend>
kannst du zusammengehörige Formularfelder visuell und semantisch gruppieren. Das ist
besonders
wichtig für Barrierefreiheit:
<fieldset>
<legend>Persönliche Daten</legend>
<label for="vorname">Vorname:</label>
<input type="text" id="vorname" name="vorname">
<label for="nachname">Nachname:</label>
<input type="text" id="nachname" name="nachname">
</fieldset>
<fieldset>
<legend>Zahlungsmethode</legend>
<label>
<input type="radio" name="zahlung" value="karte">
Kreditkarte
</label>
<label>
<input type="radio" name="zahlung" value="paypal">
PayPal
</label>
<label>
<input type="radio" name="zahlung" value="rechnung">
Rechnung
</label>
</fieldset>
Demo Browser-Default:
Demo mit CSS gestyled:
CSS anzeigen
/* Fieldset & Legend */
.demo-styled fieldset {
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 1.5rem;
margin-bottom: 1rem;
}
.demo-styled legend {
color: var(--accent-blue);
font-weight: 600;
padding: 0 0.5rem;
}
/* Form Grid für nebeneinander liegende Felder */
.demo-styled .form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
@media (max-width: 600px) {
.demo-styled .form-row {
grid-template-columns: 1fr;
}
}
/* Radio-Button Gruppe */
.demo-styled .radio-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-bottom: 1rem;
}
.demo-styled .radio-group label {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0;
cursor: pointer;
}
.demo-styled input[type="radio"] {
width: 1.25rem;
height: 1.25rem;
accent-color: var(--accent-blue);
}
Labels & Barrierefreiheit
Labels machen Formulare zugänglich - sie verbinden Beschriftungen mit Eingabefeldern. Der
for-Wert muss dem id des Feldes
entsprechen.
<!-- Explizites Label (empfohlen) -->
<label for="email">E-Mail-Adresse</label>
<input type="email" id="email" name="email" required>
<!-- Implizites Label (Input innerhalb des Labels) -->
<label>
Newsletter abonnieren
<input type="checkbox" name="newsletter">
</label>
ARIA-Attribute für bessere Zugänglichkeit
Zusätzliche Attribute helfen Screenreadern, den Inhalt korrekt wiederzugeben:
<!-- aria-label für Felder ohne sichtbares Label -->
<input type="search" aria-label="Website durchsuchen">
<!-- aria-describedby für zusätzliche Hinweise -->
<label for="passwort">Passwort</label>
<input type="password" id="passwort" aria-describedby="pw-hinweis">
<small id="pw-hinweis">Mindestens 8 Zeichen</small>
<!-- aria-required für Pflichtfelder -->
<input type="text" required aria-required="true">
<!-- aria-invalid für Validierungsfehler -->
<input type="email" aria-invalid="true" aria-errormessage="email-error">
<span id="email-error">Bitte gültige E-Mail eingeben</span>
Formularvalidierung
HTML5 bietet eingebaute Validierungsregeln - ohne JavaScript:
| Attribut | Beschreibung | Beispiel |
|---|---|---|
required |
Pflichtfeld | <input required> |
minlength / maxlength
|
Min/Max Textlänge | <input minlength="3" maxlength="20"> |
min / max |
Min/Max Zahlenwert | <input type="number" min="1" max="100"> |
pattern |
Regex-Muster | <input pattern="[A-Za-z]+"> |
step |
Erlaubte Schrittweite | <input type="number" step="0.01"> |
<!-- Nur Buchstaben, mind. 2 Zeichen -->
<input type="text"
pattern="[A-Za-zÄÖÜäöüß\s]{2,}"
title="Nur Buchstaben, mindestens 2 Zeichen"
required>
<!-- Telefonnummer -->
<input type="tel"
pattern="[\+]?[0-9\s\-]{6,}"
title="Gültige Telefonnummer eingeben">
<!-- Postleitzahl (5 Ziffern) -->
<input type="text"
pattern="[0-9]{5}"
title="5-stellige Postleitzahl">
Demo Browser-Default: Klicke auf "Prüfen".
Demo mit CSS gestyled: Klicke auf "Prüfen".
CSS anzeigen
/* Validierungsstatus visualisieren */
.demo-styled input:invalid:not(:placeholder-shown) {
border-color: #ff6b6b;
}
.demo-styled input:valid:not(:placeholder-shown) {
border-color: #51cf66;
}
/* Button Styling */
.demo-styled button {
padding: 0.75rem 1.5rem;
background: var(--color-accent, #6c9bd1);
border: none;
border-radius: 6px;
color: #fff;
font-weight: 600;
cursor: pointer;
transition: background 0.3s ease, transform 0.2s ease;
}
.demo-styled button:hover {
background: var(--color-accent-hover, #5a8ac0);
transform: translateY(-1px);
}
Sicherheit bei Formularen
HTML-Validierung ist nur die erste Verteidigungslinie - sie kann clientseitig umgangen werden. Wichtige Sicherheitsaspekte:
Niemals nur auf HTML-Validierung verlassen! Jeder kann die Browser-Validierung umgehen (DevTools, curl, etc.). Validiere immer auch serverseitig.
Best Practices
- HTTPS verwenden: Formulardaten nur über verschlüsselte Verbindungen senden
- CSRF-Schutz: Token gegen Cross-Site Request Forgery einsetzen
- Eingaben sanitisieren: Serverseitig alle Eingaben bereinigen (SQL Injection, XSS)
- Honeypot-Felder: Versteckte Felder gegen Spam-Bots
- Rate Limiting: Anzahl der Formular-Einsendungen begrenzen
<!-- Honeypot-Feld gegen Spam-Bots -->
<form action="/submit" method="post">
<!-- Dieses Feld wird per CSS versteckt -->
<!-- Bots füllen es aus, Menschen nicht -->
<input type="text" name="website" class="honeypot"
tabindex="-1" autocomplete="off">
<!-- Echte Felder -->
<input type="email" name="email" required>
<button type="submit">Absenden</button>
</form>
<style>
.honeypot {
position: absolute;
left: -9999px;
opacity: 0;
}
</style>
Die eigentliche Sicherheitslogik passiert im Backend - mehr dazu im PHP Security Tutorial.
Buttons
Buttons können Aktionen auslösen - der type bestimmt das
Verhalten:
| Typ | Beschreibung |
|---|---|
submit |
Sendet das Formular ab (Standard) |
reset |
Setzt alle Felder auf Anfangswerte zurück |
button |
Keine Standard-Aktion (für JavaScript) |
<button type="submit">Absenden</button>
<button type="reset">Zurücksetzen</button>
<button type="button" onclick="alert('Klick!')">Klick mich</button>
<!-- Button mit Icon -->
<button type="submit">
<svg>...</svg> Speichern
</button>
<!-- Deaktivierter Button -->
<button type="submit" disabled>Nicht verfügbar</button>
Demo Browser-Default:
Demo mit CSS gestyled:
CSS anzeigen
/* Buttons */
.demo-styled button {
padding: 0.75rem 1.5rem;
background: var(--color-accent, #6c9bd1);
border: none;
border-radius: 6px;
color: #fff;
font-weight: 600;
cursor: pointer;
transition: background 0.3s ease, transform 0.2s ease;
}
.demo-styled button:hover {
background: var(--color-accent-hover, #5a8ac0);
transform: translateY(-1px);
}
.demo-styled button:active {
transform: translateY(0);
}
/* Reset-Button in anderer Farbe */
.demo-styled button[type="reset"] {
background: var(--color-bg-light, #2a2a4e);
margin-left: 0.5rem;
}
.demo-styled button[type="reset"]:hover {
background: var(--color-bg-lighter, #3a3a5e);
}
/* Deaktivierte Buttons */
.demo-styled button:disabled,
.demo-styled button[disabled] {
background: var(--bg-tertiary);
color: var(--text-muted);
opacity: 0.5;
cursor: not-allowed;
}
/* Hover-Effekt bei disabled Buttons deaktivieren */
.demo-styled button:disabled:hover,
.demo-styled button[disabled]:hover {
background: var(--heading-dark);
transform: none;
box-shadow: none;
}
Praxis-Tipp: Barrierefreie Formulare
- Labels immer mit Eingabefeldern verbinden
- Fehlermeldungen klar und verständlich ausgeben
- Logische Tab-Reihenfolge sicherstellen
- Fokus sichtbar gestalten (z. B. durch CSS)
- ARIA-Attribute nur ergänzend einsetzen
- Ausreichend Kontrast für Text und Rahmen
/* Gut sichtbarer Fokus */
input:focus,
select:focus,
textarea:focus,
button:focus {
outline: 3px solid #6c9bd1;
outline-offset: 2px;
}
/* Validierungsstatus visualisieren */
input:valid {
border-color: #51cf66;
}
input:invalid {
border-color: #ff6b6b;
}
/* Pflichtfeld-Indikator */
label.required::after {
content: " *";
color: #ff6b6b;
}
Praxisbeispiel: Kontaktformular
Hier ein vollständiges Kontaktformular mit Betreffzeile, wie es auf der DevPanicZone aussehen könnte. Das Formular ist barrierefrei, validiert und responsiv.
<form action="/kontakt-verarbeiten.php" method="post" class="dpz-contact-form">
<h3>Kontakt aufnehmen</h3>
<div class="form-group">
<label for="contact-name">Name *</label>
<input type="text" id="contact-name" name="name"
placeholder="Dein Name" required>
</div>
<div class="form-group">
<label for="contact-email">E-Mail *</label>
<input type="email" id="contact-email" name="email"
placeholder="[email protected]" required>
</div>
<div class="form-group">
<label for="contact-subject">Betreff *</label>
<select id="contact-subject" name="subject" required>
<option value="">Bitte wählen...</option>
<option value="feedback">Feedback zum Tutorial</option>
<option value="fehler">Fehler melden</option>
<option value="vorschlag">Themenvorschlag</option>
<option value="sonstiges">Sonstiges</option>
</select>
</div>
<div class="form-group">
<label for="contact-message">Nachricht *</label>
<textarea id="contact-message" name="message"
placeholder="Deine Nachricht..." required></textarea>
</div>
<div class="form-actions">
<button type="submit" class="btn-submit">Nachricht senden</button>
<button type="reset" class="btn-reset">Zurücksetzen</button>
</div>
<p class="privacy-note">* Pflichtfelder. Deine Daten werden nicht gespeichert.</p>
</form>
Live-Demo
So würde das Kontaktformular auf der DevPanicZone aussehen:
CSS anzeigen
/* DevPanicZone Kontaktformular */
.dpz-contact-form {
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 2rem;
}
.dpz-contact-form .form-group {
margin-bottom: 1.25rem;
}
.dpz-contact-form label {
display: block;
margin-bottom: 0.5rem;
color: var(--text-primary);
font-weight: 500;
font-size: 0.9rem;
}
.dpz-contact-form input,
.dpz-contact-form select,
.dpz-contact-form textarea {
width: 100%;
padding: 0.875rem 1rem;
background: var(--bg-tertiary);
border: 1px solid var(--border-color);
border-radius: 8px;
color: var(--text-primary);
font-size: 1rem;
font-family: inherit;
transition: all 0.3s ease;
}
.dpz-contact-form input:focus,
.dpz-contact-form select:focus,
.dpz-contact-form textarea:focus {
outline: none;
border-color: var(--accent-blue-light);
box-shadow: 0 0 0 3px rgba(108, 155, 209, 0.15);
background: var(--bg-tertiary);
}
.dpz-contact-form textarea {
min-height: 150px;
resize: vertical;
}
.dpz-contact-form .form-actions {
display: flex;
gap: 1rem;
margin-top: 1.5rem;
}
.dpz-contact-form .btn-submit {
flex: 1;
padding: 1rem 2rem;
background: var(--accent-blue-light);
border: none;
border-radius: 8px;
color: #fff;
font-weight: 600;
font-size: 1rem;
cursor: pointer;
transition: all 0.3s ease;
}
.dpz-contact-form .btn-submit:hover {
background: var(--accent-blue-light);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(108, 155, 209, 0.4);
}
.dpz-contact-form .btn-reset {
padding: 1rem 1.5rem;
background: transparent;
border: 1px solid var(--border-color);
border-radius: 8px;
color: var(--text-muted);
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
}
.dpz-contact-form .btn-reset:hover {
border-color: var(--border-color);
color: var(--text-primary);
}
.dpz-contact-form .privacy-note {
font-size: 0.8rem;
color: var(--text-muted);
margin-top: 1rem;
text-align: center;
}
Alternative: 2-Spalten-Layout
Für breitere Layouts kannst du das Formular in zwei Spalten aufteilen - links die kurzen Felder, rechts die Nachricht:
<form action="/kontakt-verarbeiten.php" method="post" class="dpz-contact-form-wide">
<h3>Kontakt aufnehmen</h3>
<div class="form-columns">
<!-- Linke Spalte -->
<div class="form-column-left">
<div class="form-group">
<label for="contact-name">Name *</label>
<input type="text" id="contact-name" name="name"
placeholder="Dein Name" required>
</div>
<div class="form-group">
<label for="contact-email">E-Mail *</label>
<input type="email" id="contact-email" name="email"
placeholder="[email protected]" required>
</div>
<div class="form-group">
<label for="contact-subject">Betreff *</label>
<select id="contact-subject" name="subject" required>
<option value="">Bitte wählen...</option>
<option value="feedback">Feedback zum Tutorial</option>
<option value="fehler">Fehler melden</option>
<option value="vorschlag">Themenvorschlag</option>
<option value="sonstiges">Sonstiges</option>
</select>
</div>
</div>
<!-- Rechte Spalte -->
<div class="form-column-right">
<div class="form-group">
<label for="contact-message">Nachricht *</label>
<textarea id="contact-message" name="message"
placeholder="Deine Nachricht..." required></textarea>
</div>
<div class="form-actions">
<button type="submit" class="btn-submit">Senden</button>
<button type="reset" class="btn-reset">Zurücksetzen</button>
</div>
</div>
</div>
<p class="privacy-note">* Pflichtfelder</p>
</form>
CSS anzeigen
/* 2-Spalten Kontaktformular */
.dpz-contact-form-wide {
width: 100%;
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 2rem;
}
.dpz-contact-form-wide h3 {
margin-top: 0;
margin-bottom: 1.5rem;
color: var(--accent-blue-light);
font-size: 1.5rem;
}
.dpz-contact-form-wide .form-columns {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
}
@media (max-width: 768px) {
.dpz-contact-form-wide .form-columns {
grid-template-columns: 1fr;
gap: 0;
}
}
.dpz-contact-form-wide .form-column-left,
.dpz-contact-form-wide .form-column-right {
display: flex;
flex-direction: column;
}
.dpz-contact-form-wide .form-group {
margin-bottom: 1.25rem;
}
.dpz-contact-form-wide label {
display: block;
margin-bottom: 0.5rem;
color: var(--text-primary);
font-weight: 500;
font-size: 0.9rem;
}
.dpz-contact-form-wide input,
.dpz-contact-form-wide select,
.dpz-contact-form-wide textarea {
width: 100%;
padding: 0.875rem 1rem;
background: var(--bg-tertiary);
border: 1px solid var(--border-color);
border-radius: 8px;
color: var(--text-primary);
font-size: 1rem;
font-family: inherit;
transition: all 0.3s ease;
}
.dpz-contact-form-wide input:focus,
.dpz-contact-form-wide select:focus,
.dpz-contact-form-wide textarea:focus {
outline: none;
border-color: var(--accent-blue-hover);
box-shadow: 0 0 0 3px rgba(108, 155, 209, 0.15);
background: var(--bg-primary);
}
.dpz-contact-form-wide .form-column-right {
display: flex;
flex-direction: column;
}
.dpz-contact-form-wide .form-column-right .form-group {
flex: 1;
display: flex;
flex-direction: column;
}
.dpz-contact-form-wide .form-column-right textarea {
flex: 1;
min-height: 120px;
resize: vertical;
}
.dpz-contact-form-wide .form-actions {
display: flex;
gap: 1rem;
margin-top: 1rem;
}
.dpz-contact-form-wide .btn-submit {
flex: 1;
padding: 1rem 2rem;
background: var(--accent-blue-light);
border: none;
border-radius: 8px;
color: #fff;
font-weight: 600;
font-size: 1rem;
cursor: pointer;
transition: all 0.3s ease;
}
.dpz-contact-form-wide .btn-submit:hover {
background: var(--color-accent-hover, #5a8ac0);
transform: translateY(-2px);
/* box-shadow: 0 4px 12px rgba(108, 155, 209, 0.4); */
}
.dpz-contact-form-wide .btn-reset {
padding: 1rem 1.5rem;
background: transparent;
border: 1px solid var(--border-color);
border-radius: 8px;
color: var(--text-muted);
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
}
.dpz-contact-form-wide .btn-reset:hover {
border-color: var(--border-color);
color: var(--text-primary);
}
.dpz-contact-form-wide .privacy-note {
font-size: 0.8rem;
color: var(--text-muted);
margin-top: 1rem;
text-align: center;
grid-column: 1 / -1;
}
Diese Formulare sind nur Demos - um sie funktionsfähig zu machen, brauchst du ein Backend (z. B. PHP), das die Daten verarbeitet und die E-Mail versendet. Das behandeln wir im PHP-Tutorial!
Mehr aus HTML
Tutorials werden geladen...