Responsive Tabellen und Formulare
Tabellen und Formulare benötigen auf schmalen Viewports besondere
Aufmerksamkeit. Breite Tabellen können horizontal über den sichtbaren Bereich
hinausragen, während mehrspaltige Formulare auf kleinen Bildschirmen schnell
unĂĽbersichtlich werden.
Responsive Lösungen sorgen dafür, dass Informationen vollständig erhalten
bleiben, Formularfelder gut bedienbar sind und die ursprĂĽngliche semantische
Struktur nicht verloren geht.
Die Herausforderung breiter Tabellen
Tabellen passen sich nicht immer automatisch an einen schmalen Container an.
Besonders viele Spalten, lange Bezeichnungen und Inhalte ohne geeignete
Umbruchstellen können horizontalen Überlauf verursachen.
<table>
<thead>
<tr>
<th>Artikelnummer</th>
<th>Produktbezeichnung</th>
<th>Kategorie</th>
<th>Einzelpreis</th>
<th>Lagerbestand</th>
</tr>
</thead>
<tbody>
<tr>
<td>A-1001</td>
<td>Notebook mit Zubehörpaket</td>
<td>Computer</td>
<td>1.249,00 €</td>
<td>12 StĂĽck</td>
</tr>
</tbody>
</table>
Inhalte oder Spalten sollten nicht einfach ausgeblendet werden, wenn dadurch
wichtige Informationen verloren gehen.
Grundlegende Tabellenformatierung
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
padding: 0.75rem;
border: 1px solid #ced4da;
text-align: left;
vertical-align: top;
}
thead {
background-color: #e9ecef;
}
tbody tr:nth-child(even) {
background-color: #f8f9fa;
}
Mit width: 100% verwendet die Tabelle mindestens die verfĂĽgbare
Containerbreite. Das allein verhindert jedoch nicht, dass eine inhaltlich
breite Tabelle ĂĽber den Container hinausragt.
Tabellen horizontal scrollbar machen
Die zuverlässigste Standardlösung für breite Tabellen ist ein äußerer
Scroll-Container.
<div
class="table-wrapper"
tabindex="0"
role="region"
aria-label="ProduktĂĽbersicht"
>
<table>
...
</table>
</div>
.table-wrapper {
max-width: 100%;
overflow-x: auto;
overscroll-behavior-inline: contain;
}
.table-wrapper table {
min-width: 50rem;
}
Die Tabelle behält mit min-width ausreichend Platz für ihre
Spalten. Auf schmalen Viewports kann innerhalb des Wrappers horizontal
gescrollt werden.
tabindex="0" macht den Scrollbereich mit der Tastatur
fokussierbar. Eine sichtbare Fokusmarkierung darf dabei nicht entfernt werden.
Bootstrap: table-responsive
Bootstrap stellt fĂĽr horizontal scrollbar dargestellte Tabellen die Klasse
table-responsive bereit.
<div class="table-responsive">
<table class="table table-striped table-bordered align-middle">
...
</table>
</div>
Der Wrapper erhält bei Bedarf einen horizontalen Scrollbereich. Die
Tabellenstruktur selbst bleibt unverändert.
Bootstrap bietet außerdem breakpointabhängige Varianten:
table-responsive-sm
table-responsive-md
table-responsive-lg
table-responsive-xl
table-responsive-xxl
Bei table-responsive-md wird der Scrollbereich nur unterhalb des
Breakpoints md verwendet. Für eine allgemein robuste Lösung
eignet sich häufig table-responsive ohne Breakpoint.
Spaltenbreiten und Textumbruch
.product-table {
table-layout: fixed;
}
.product-table th:nth-child(1) {
width: 8rem;
}
.product-table th:nth-child(4) {
width: 9rem;
}
.product-table th,
.product-table td {
overflow-wrap: anywhere;
}
Mit table-layout: fixed orientiert sich die Spaltenaufteilung
stärker an der Tabellenbreite und den festgelegten Spaltenbreiten. Lange
Inhalte müssen dabei geeignete Umbruchmöglichkeiten erhalten.
table-layout: fixed ist nicht fĂĽr jede Tabelle geeignet. Bei
vielen unterschiedlich langen Inhalten kann der automatische Tabellenalgorithmus
besser lesbare Spaltenbreiten erzeugen.
Inhalte gezielt nicht umbrechen
.table-price,
.table-date {
white-space: nowrap;
}
Kurze zusammengehörige Angaben wie Preise, Datumswerte oder Statusangaben
können mit white-space: nowrap in einer Zeile gehalten werden.
white-space: nowrap sollte nur gezielt eingesetzt werden. Bei
vielen Spalten kann es die Tabelle erheblich verbreitern.
Eine Tabellenbeschriftung verwenden
<table>
<caption>
Produktbestand, Stand: Juli 2026
</caption>
...
</table>
caption {
padding-block: 0.75rem;
font-weight: 700;
text-align: left;
caption-side: top;
}
Das Element <caption> beschreibt den Inhalt oder Zweck
einer Tabelle. Es ist semantisch mit der Tabelle verbunden und verbessert
dadurch auch die Zugänglichkeit.
TabellenĂĽberschriften korrekt zuordnen
<table>
<thead>
<tr>
<th scope="col">Produkt</th>
<th scope="col">Preis</th>
<th scope="col">Bestand</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Notebook</th>
<td>1.249,00 €</td>
<td>12</td>
</tr>
</tbody>
</table>
scope="col" kennzeichnet eine SpaltenĂĽberschrift.
scope="row" kennzeichnet eine ZeilenĂĽberschrift. Assistive
Technologien können Datenzellen dadurch leichter den richtigen Überschriften
zuordnen.
Komplexe Tabellen vermeiden
Tabellen mit mehreren Ăśberschriftsebenen, verbundenen Zellen und zahlreichen
Spalten sind auf kleinen Bildschirmen und fĂĽr Screenreader schwieriger
verständlich.
- Tabellen möglichst einfach strukturieren.
- Zusammengehörige Informationen sinnvoll gruppieren.
- Unabhängige Datengruppen gegebenenfalls auf mehrere Tabellen verteilen.
colspan und rowspan nur verwenden, wenn nötig.
- Eine verständliche Beschriftung mit
<caption> ergänzen.
Eine Tabelle sollte fĂĽr tabellarische Daten verwendet werden und nicht zur
Gestaltung des Seitenlayouts.
Tabellen auf Karten umstellen
Tabellenzeilen können auf schmalen Viewports optisch als Karten dargestellt
werden. DafĂĽr mĂĽssen die Spaltenbezeichnungen in jeder Datenzelle verfĂĽgbar
sein.
<table class="responsive-table">
<thead>
<tr>
<th scope="col">Produkt</th>
<th scope="col">Preis</th>
<th scope="col">Bestand</th>
</tr>
</thead>
<tbody>
<tr>
<td data-label="Produkt">Notebook</td>
<td data-label="Preis">1.249,00 €</td>
<td data-label="Bestand">12 StĂĽck</td>
</tr>
</tbody>
</table>
@media (max-width: 47.999rem) {
.responsive-table,
.responsive-table tbody,
.responsive-table tr,
.responsive-table td {
display: block;
width: 100%;
}
.responsive-table thead {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.responsive-table tr {
margin-bottom: 1rem;
border: 1px solid #ced4da;
border-radius: 0.5rem;
}
.responsive-table td {
display: grid;
grid-template-columns: minmax(7rem, 40%) 1fr;
gap: 1rem;
padding: 0.75rem;
border: 0;
border-bottom: 1px solid #dee2e6;
}
.responsive-table td:last-child {
border-bottom: 0;
}
.responsive-table td::before {
content: attr(data-label);
font-weight: 700;
}
}
Diese Darstellung eignet sich nicht automatisch fĂĽr jede Tabelle. Bei
umfangreichen Datenvergleichen ist horizontales Scrollen häufig verständlicher,
weil die Spaltenbeziehungen sichtbar bleiben.
Grundstruktur eines zugänglichen Formulars
<form action="kontakt.php" method="post">
<div class="form-field">
<label for="firstname">Vorname</label>
<input
type="text"
id="firstname"
name="firstname"
autocomplete="given-name"
required
>
</div>
<div class="form-field">
<label for="email">E-Mail-Adresse</label>
<input
type="email"
id="email"
name="email"
autocomplete="email"
required
>
</div>
<button type="submit">Absenden</button>
</form>
Jedes Formularfeld benötigt eine eindeutige Beschriftung. Das
for-Attribut des Labels muss mit der id des
zugehörigen Feldes übereinstimmen.
Formularfelder flexibel darstellen
form {
width: min(100%, 50rem);
}
.form-field {
display: grid;
gap: 0.375rem;
}
input,
select,
textarea,
button {
font: inherit;
}
input,
select,
textarea {
width: 100%;
min-width: 0;
padding: 0.75rem;
border: 1px solid #6c757d;
border-radius: 0.375rem;
}
textarea {
min-height: 10rem;
resize: vertical;
}
width: 100% lässt die Felder den verfügbaren Platz ausfüllen.
min-width: 0 verhindert, dass Grid- oder Flex-Elemente wegen
langer Inhalte unnötig über ihren Container hinausragen.
Mit font: inherit ĂĽbernehmen Formularelemente die Schrift des
Dokuments und wirken dadurch einheitlicher.
Einspaltig beginnen: Small Device First
.form-grid {
display: grid;
gap: 1rem;
}
Auf kleinen Viewports werden Formularfelder zunächst untereinander angeordnet.
Diese Darstellung ist übersichtlich und lässt genügend Platz für
Beschriftungen, Eingaben und Fehlermeldungen.
<div class="form-grid">
<div class="form-field">
<label for="firstname2">Vorname</label>
<input type="text" id="firstname2" name="firstname">
</div>
<div class="form-field">
<label for="lastname">Nachname</label>
<input type="text" id="lastname" name="lastname">
</div>
</div>
Mehrspaltige Formulare ab einem Breakpoint
.form-grid {
display: grid;
gap: 1rem;
}
@media (min-width: 48rem) {
.form-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.form-field-full {
grid-column: 1 / -1;
}
}
<div class="form-grid">
<div class="form-field">
...
</div>
<div class="form-field">
...
</div>
<div class="form-field form-field-full">
...
</div>
</div>
Erst wenn ausreichend Platz vorhanden ist, wird das Formular zweispaltig.
Breite Felder wie Nachrichten oder Adressen können mit
grid-column: 1 / -1 ĂĽber alle Spalten reichen.
Formulare ohne Media Query anordnen
.form-grid-auto {
display: grid;
grid-template-columns:
repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
gap: 1rem;
}
.form-field-full {
grid-column: 1 / -1;
}
auto-fit erzeugt so viele Spalten, wie in den Container passen.
Mit min(100%, 16rem) kann eine Spalte auf sehr schmalen
Containern kleiner als 16rem werden, ohne horizontalen Ăśberlauf
zu verursachen.
Formulargruppen mit fieldset
<fieldset>
<legend>Bevorzugte Layouttechnik</legend>
<div class="choice-field">
<input
type="radio"
id="layout-flexbox"
name="layout"
value="flexbox"
>
<label for="layout-flexbox">Flexbox</label>
</div>
<div class="choice-field">
<input
type="radio"
id="layout-grid"
name="layout"
value="grid"
>
<label for="layout-grid">CSS Grid</label>
</div>
</fieldset>
fieldset {
min-width: 0;
margin: 0;
padding: 1rem;
border: 1px solid #ced4da;
border-radius: 0.5rem;
}
legend {
padding-inline: 0.375rem;
font-weight: 700;
}
.choice-field {
display: flex;
align-items: flex-start;
gap: 0.625rem;
}
.choice-field + .choice-field {
margin-top: 0.75rem;
}
<fieldset> gruppiert zusammengehörige Felder.
<legend> beschreibt die gesamte Gruppe. Das ist besonders
bei Radio-Buttons und Kontrollkästchen wichtig.
Ausreichend große Bedienflächen
button,
input[type="button"],
input[type="submit"],
input[type="reset"] {
min-height: 2.75rem;
padding: 0.625rem 1rem;
cursor: pointer;
}
.choice-field input {
width: 1.25rem;
height: 1.25rem;
margin-top: 0.125rem;
}
Schaltflächen, Kontrollkästchen und Radio-Buttons müssen auch auf
Touchscreens gut bedienbar sein. Das zugehörige
<label> vergrößert bei korrekt hergestellter Verbindung
ebenfalls die anklickbare Fläche.
Sichtbare Fokusmarkierungen
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
button:focus-visible {
outline: 3px solid #0d6efd;
outline-offset: 2px;
}
Eine deutliche Fokusmarkierung zeigt, welches Element gerade mit der Tastatur
bedient wird.
outline: none darf nicht ohne eine mindestens gleichwertige
sichtbare Alternative verwendet werden.
Hinweise und Pflichtfelder kennzeichnen
<label for="password">
Passwort
<span aria-hidden="true">*</span>
</label>
<input
type="password"
id="password"
name="password"
autocomplete="new-password"
aria-describedby="password-help"
required
>
<p id="password-help" class="form-help">
Mindestens zwölf Zeichen verwenden. Pflichtfeld.
</p>
.form-help {
margin: 0;
color: #495057;
font-size: 0.875rem;
}
Mit aria-describedby wird der Hilfetext programmatisch mit dem
Eingabefeld verbunden. Eine Kennzeichnung nur durch ein Sternchen sollte
zusätzlich verständlich erklärt werden.
Fehlermeldungen verständlich ausgeben
<div class="form-field form-field-error">
<label for="email2">E-Mail-Adresse</label>
<input
type="email"
id="email2"
name="email"
aria-invalid="true"
aria-describedby="email-error"
>
<p id="email-error" class="error-message">
Bitte geben Sie eine gĂĽltige E-Mail-Adresse ein.
</p>
</div>
.form-field-error input {
border-color: #b02a37;
}
.error-message {
margin: 0;
color: #b02a37;
font-weight: 600;
}
Fehler dĂĽrfen nicht ausschlieĂźlich durch eine Farbe angezeigt werden.
Zusätzlich ist eine konkrete Textmeldung erforderlich, die erklärt, wie der
Fehler behoben werden kann.
Nach dem Absenden sollte der Fokus sinnvoll zum ersten fehlerhaften Feld oder
zu einer zusammenfassenden Fehlerliste gefĂĽhrt werden.
Passende Eingabetypen und autocomplete
<input
type="email"
name="email"
autocomplete="email"
>
<input
type="tel"
name="phone"
autocomplete="tel"
>
<input
type="text"
name="postal-code"
inputmode="numeric"
autocomplete="postal-code"
>
Passende Eingabetypen und Autocomplete-Werte erleichtern die Eingabe,
insbesondere auf mobilen Geräten.
| Angabe |
Aufgabe |
type="email" |
Erwartet eine E-Mail-Adresse. |
type="tel" |
Ist fĂĽr Telefonnummern vorgesehen. |
inputmode="numeric" |
Fordert auf mobilen Geräten eine passende Bildschirmtastatur an. |
autocomplete |
Beschreibt die Bedeutung des Feldes fĂĽr automatische Eingabehilfen. |
Postleitzahlen, Telefonnummern und Kundennummern sind keine Zahlen fĂĽr
mathematische Berechnungen. Häufig ist type="text" mit einem
geeigneten inputmode besser als type="number".
Bootstrap-Formular mit responsivem Grid
<form class="row g-3">
<div class="col-12 col-md-6">
<label for="firstname3" class="form-label">
Vorname
</label>
<input
type="text"
class="form-control"
id="firstname3"
name="firstname"
autocomplete="given-name"
>
</div>
<div class="col-12 col-md-6">
<label for="lastname3" class="form-label">
Nachname
</label>
<input
type="text"
class="form-control"
id="lastname3"
name="lastname"
autocomplete="family-name"
>
</div>
<div class="col-12">
<label for="message" class="form-label">
Nachricht
</label>
<textarea
class="form-control"
id="message"
name="message"
rows="6"
></textarea>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary">
Nachricht absenden
</button>
</div>
</form>
Mit col-12 sind die Felder auf kleinen Viewports einspaltig.
Ab dem Breakpoint md erhalten Vorname und Nachname mit
col-md-6 jeweils eine halbe Zeile.
Ein vollständiges responsives Formular
<form class="contact-form" action="kontakt.php" method="post">
<div class="form-grid">
<div class="form-field">
<label for="contact-firstname">Vorname</label>
<input
type="text"
id="contact-firstname"
name="firstname"
autocomplete="given-name"
required
>
</div>
<div class="form-field">
<label for="contact-lastname">Nachname</label>
<input
type="text"
id="contact-lastname"
name="lastname"
autocomplete="family-name"
required
>
</div>
<div class="form-field form-field-full">
<label for="contact-email">E-Mail-Adresse</label>
<input
type="email"
id="contact-email"
name="email"
autocomplete="email"
required
>
</div>
<div class="form-field form-field-full">
<label for="contact-subject">Betreff</label>
<select id="contact-subject" name="subject" required>
<option value="">Bitte auswählen</option>
<option value="html">HTML und CSS</option>
<option value="php">PHP</option>
<option value="excel">Excel</option>
</select>
</div>
<div class="form-field form-field-full">
<label for="contact-message">Nachricht</label>
<textarea
id="contact-message"
name="message"
rows="8"
required
></textarea>
</div>
<div class="form-field-full">
<button type="submit">Nachricht absenden</button>
</div>
</div>
</form>
.contact-form {
width: min(100%, 50rem);
margin-inline: auto;
}
.form-grid {
display: grid;
gap: 1rem;
}
.form-field {
display: grid;
align-content: start;
gap: 0.375rem;
min-width: 0;
}
.form-field label {
font-weight: 700;
}
.form-field input,
.form-field select,
.form-field textarea {
width: 100%;
min-width: 0;
padding: 0.75rem;
color: #212529;
background-color: #ffffff;
border: 1px solid #6c757d;
border-radius: 0.375rem;
font: inherit;
}
.form-field textarea {
min-height: 10rem;
resize: vertical;
}
.contact-form button {
min-height: 2.75rem;
padding: 0.75rem 1.25rem;
color: #ffffff;
background-color: #0d6efd;
border: 0;
border-radius: 0.375rem;
font: inherit;
font-weight: 700;
cursor: pointer;
}
.contact-form :focus-visible {
outline: 3px solid #fd7e14;
outline-offset: 2px;
}
@media (min-width: 48rem) {
.form-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.form-field-full {
grid-column: 1 / -1;
}
}
Häufige Fehler
-
Eine breite Tabelle ragt ohne Scroll-Container ĂĽber den Viewport hinaus.
-
Wichtige Tabellenspalten werden auf kleinen Viewports vollständig
ausgeblendet.
-
Tabellen werden fĂĽr das Seitenlayout statt fĂĽr tabellarische Daten
verwendet.
-
Spalten- und ZeilenĂĽberschriften sind nicht mit
<th> und scope gekennzeichnet.
-
Eine Tabelle besitzt keine verständliche Beschriftung.
-
Formulare sind bereits auf kleinen Viewports mehrspaltig.
-
Eingabefelder besitzen feste Breiten und ragen aus dem Container heraus.
-
Platzhalter werden anstelle sichtbarer Beschriftungen verwendet.
-
Das
for-Attribut eines Labels stimmt nicht mit der
id des Feldes ĂĽberein.
-
Fehlermeldungen werden ausschlieĂźlich durch eine rote Rahmenfarbe
angezeigt.
-
Fokusmarkierungen werden mit
outline: none entfernt.
-
Zusammengehörige Radio-Buttons oder Kontrollkästchen besitzen kein
<fieldset> mit <legend>.
-
Schaltflächen und Auswahlfelder sind auf Touchscreens zu klein.
-
FĂĽr Postleitzahlen oder Telefonnummern wird ungeeignetes
type="number" verwendet.
-
Hilfs- und Fehlermeldungen sind nicht programmatisch mit dem jeweiligen
Formularfeld verbunden.
Zusammenfassung
-
Breite Tabellen können in einem Wrapper mit
overflow-x: auto horizontal scrollbar dargestellt werden.
-
Bootstrap stellt dafĂĽr die Klasse
table-responsive bereit.
-
<caption> beschreibt den Inhalt einer Tabelle.
-
scope="col" und scope="row" ordnen
TabellenĂĽberschriften den Datenzellen zu.
-
Eine Kartendarstellung eignet sich nur fĂĽr Tabellen, deren Datenbeziehungen
dabei verständlich bleiben.
-
Formulare sollten nach dem Small-Device-First-Prinzip zunächst einspaltig
aufgebaut werden.
-
CSS Grid und Media Queries ermöglichen mehrspaltige Formulare auf breiteren
Viewports.
-
Jedes Eingabefeld benötigt eine sichtbare und eindeutig zugeordnete
Beschriftung.
-
<fieldset> und <legend>
gruppieren zusammengehörige Auswahlfelder.
-
Fehlermeldungen müssen verständlich formuliert und mit dem jeweiligen Feld
verbunden werden.
-
Sichtbare Fokusmarkierungen und ausreichend große Bedienflächen verbessern
die Tastatur- und Touchbedienung.
-
Passende Eingabetypen,
inputmode und
autocomplete erleichtern die Dateneingabe.
Responsive Tabellen bewahren vollständige Daten, ohne das Seitenlayout zu
sprengen. Responsive Formulare passen ihre Anordnung an den verfĂĽgbaren Platz
an und bleiben mit Tastatur, Touchscreen und assistiven Technologien
zuverlässig bedienbar.