Anfänger142024-01-15

Das <button> Element - Interaktive Schaltflächen

Vollständige Referenz zum HTML <button> Element: Typen, Attribute, States, Accessibility, Button vs Link und Best Practices

#html#element#button#form#interactive#accessibility

Das <button> Element

Das <button>-Element erstellt klickbare Schaltflächen. Im Gegensatz zu Links (<a>) werden Buttons für Aktionen verwendet, nicht für Navigation.

Syntax

<button>Klick mich</button>

Grundlegende Eigenschaften

Element-Typ

  • Display: inline-block
  • Kategorie: Flow content, phrasing content, interactive content
  • Erlaubter Inhalt: Phrasing content (KEIN interaktiver Content)
  • Standard-Typ: submit (innerhalb von <form>)

Button vs Link - Wann was?

Use CaseElementGrund
Navigation zu anderer Seite<a>Semantisch korrekt
Aktion ausführen<button>Semantisch korrekt
Formular absenden<button type="submit">Standard-Verhalten
Modal öffnen<button>Aktion, keine Navigation
Dropdown toggle<button>Aktion
JavaScript-Funktion<button>Aktion
Download starten<a download>Navigation zu Ressource

Wann verwenden?

  • Form-Submits
  • Modals/Dialogs öffnen
  • JavaScript-Aktionen ausführen
  • Dropdown-Menüs toggeln
  • Daten ändern (Löschen, Speichern, etc.)

Wann NICHT verwenden?

  • ❌ Für Navigation (nutze <a>)
  • ❌ Als Container für Layout
  • ❌ Wenn Button nichts tut (deaktiviere mit disabled)

Attribute

type - Button-Typ

<!-- Submit (Standard in Forms) -->
<button type="submit">Absenden</button>

<!-- Reset (Formular zurücksetzen) -->
<button type="reset">Zurücksetzen</button>

<!-- Button (keine Standard-Aktion) -->
<button type="button">Klick mich</button>

Wichtig: Ohne type ist der Standard:

  • submit innerhalb von <form>
  • kein Standard außerhalb von <form>

disabled - Button deaktivieren

<!-- Deaktivierter Button -->
<button disabled>Nicht klickbar</button>

<!-- Mit JavaScript toggle -->
<button id="submit-btn">Absenden</button>

<script>
  const btn = document.getElementById('submit-btn');
  btn.disabled = true;  // Deaktivieren
  btn.disabled = false; // Aktivieren
</script>

Effekte von disabled:

  • ❌ Nicht klickbar
  • ❌ Nicht fokussierbar (Tastatur)
  • ❌ Nicht in Formular-Submit enthalten
  • 🎨 Visuell ausgegraut

name & value - Formular-Daten

<form>
  <button type="submit" name="action" value="save">
    Speichern
  </button>
  <button type="submit" name="action" value="delete">
    Löschen
  </button>
</form>
// Server-seitig auswerten
if ($_POST['action'] === 'save') {
  // Speichern
} else if ($_POST['action'] === 'delete') {
  // Löschen
}

form - Mit Form verknüpfen

<!-- Button außerhalb des Forms -->
<button type="submit" form="my-form">
  Absenden
</button>

<form id="my-form">
  <input type="text" name="username">
</form>

formaction - Submit-Ziel überschreiben

<form action="/save">
  <input type="text" name="data">

  <!-- Standard: /save -->
  <button type="submit">Speichern</button>

  <!-- Überschrieben: /draft -->
  <button type="submit" formaction="/draft">
    Als Entwurf speichern
  </button>
</form>

formmethod - HTTP-Method überschreiben

<form method="POST">
  <button type="submit">POST (Standard)</button>
  <button type="submit" formmethod="GET">
    Als GET senden
  </button>
</form>

formtarget - Target überschreiben

<form target="_self">
  <button type="submit">
    Gleiches Fenster
  </button>
  <button type="submit" formtarget="_blank">
    Neues Fenster
  </button>
</form>

formnovalidate - Validation überspringen

<form>
  <input type="email" required>

  <!-- Mit Validation -->
  <button type="submit">Absenden</button>

  <!-- Ohne Validation -->
  <button type="submit" formnovalidate>
    Als Entwurf speichern
  </button>
</form>

autofocus - Automatisch fokussieren

<!-- Button erhält Fokus beim Laden -->
<button autofocus>Primäre Aktion</button>

⚠️ Vorsicht: Nur 1x pro Seite verwenden!

Default CSS-Eigenschaften

button {
  /* Display */
  display: inline-block;

  /* Text */
  font-family: inherit;
  font-size: inherit;
  line-height: normal;
  text-align: center;

  /* Box Model */
  margin: 0;
  padding: 2px 6px;
  border: 2px outset buttonface;
  border-radius: 0;

  /* Colors */
  background-color: buttonface;  /* System-Farbe */
  color: buttontext;

  /* Cursor */
  cursor: pointer;

  /* States */
  appearance: button;
  user-select: none;
}

button:disabled {
  cursor: not-allowed;
  opacity: 0.5;
  pointer-events: none;
}

button:focus {
  outline: 2px solid Highlight;
  outline-offset: 2px;
}

Button-States (Pseudo-Klassen)

/* Normal */
button { }

/* Hover */
button:hover {
  background-color: #0052a3;
}

/* Active (beim Klicken) */
button:active {
  transform: scale(0.98);
}

/* Focus (Tastatur) */
button:focus {
  outline: 2px solid #0066cc;
}

/* Focus Visible (nur Tastatur, nicht Maus) */
button:focus-visible {
  outline: 2px solid #0066cc;
}

/* Disabled */
button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Focus within (wenn Kind-Element Fokus hat) */
button:focus-within { }

Praktische Beispiele

1. Primary & Secondary Buttons

<button class="btn btn-primary">Primär</button>
<button class="btn btn-secondary">Sekundär</button>
<button class="btn btn-danger">Löschen</button>
.btn {
  padding: 10px 20px;
  border: none;
  border-radius: 6px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s;
}

.btn-primary {
  background-color: #0066cc;
  color: white;
}

.btn-primary:hover {
  background-color: #0052a3;
}

.btn-secondary {
  background-color: #6c757d;
  color: white;
}

.btn-danger {
  background-color: #dc3545;
  color: white;
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

2. Icon Button

<button class="icon-btn" aria-label="Einstellungen">
  <svg><!-- Icon --></svg>
</button>
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background-color: #f0f0f0;
  cursor: pointer;
  transition: background-color 0.2s;
}

.icon-btn:hover {
  background-color: #e0e0e0;
}

3. Loading State

<button id="submit-btn" class="btn btn-primary">
  <span class="btn-text">Absenden</span>
  <span class="btn-loader" hidden>
    <span class="spinner"></span>
    Lädt...
  </span>
</button>
const btn = document.getElementById('submit-btn');
const text = btn.querySelector('.btn-text');
const loader = btn.querySelector('.btn-loader');

btn.addEventListener('click', async () => {
  // Loading aktivieren
  btn.disabled = true;
  text.hidden = true;
  loader.hidden = false;

  try {
    await fetchData();
  } finally {
    // Loading deaktivieren
    btn.disabled = false;
    text.hidden = false;
    loader.hidden = true;
  }
});
.spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-radius: 50%;
  border-top-color: white;
  animation: spin 0.6s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

4. Button Group

<div class="btn-group">
  <button class="btn active">Links</button>
  <button class="btn">Mitte</button>
  <button class="btn">Rechts</button>
</div>
.btn-group {
  display: inline-flex;
  gap: 0;
}

.btn-group .btn {
  border-radius: 0;
  border-right: none;
}

.btn-group .btn:first-child {
  border-top-left-radius: 6px;
  border-bottom-left-radius: 6px;
}

.btn-group .btn:last-child {
  border-right: 1px solid #ddd;
  border-top-right-radius: 6px;
  border-bottom-right-radius: 6px;
}

.btn-group .btn.active {
  background-color: #0066cc;
  color: white;
}

5. Confirmation Button

<button
  id="delete-btn"
  class="btn btn-danger"
  data-confirm="Wirklich löschen?"
>
  Löschen
</button>
document.getElementById('delete-btn').addEventListener('click', (e) => {
  const msg = e.target.dataset.confirm;
  if (!confirm(msg)) {
    e.preventDefault();
    return;
  }
  // Löschen durchführen
});

Best Practices

✅ DO (Empfohlen)

<!-- Klarer Button-Text -->
<button type="button">Speichern</button>

<!-- Type explizit setzen -->
<button type="submit">Absenden</button>
<button type="button">Abbrechen</button>

<!-- Disabled für inaktive Buttons -->
<button disabled>Nicht verfügbar</button>

<!-- Aria-Label für Icon-Buttons -->
<button aria-label="Menü öffnen">
  ☰
</button>

<!-- Loading-State -->
<button disabled aria-busy="true">
  Lädt...
</button>

❌ DON'T (Vermeiden)

<!-- Link-Funktionalität mit Button -->
<button onclick="location.href='/page'">  <!-- ❌ Nutze <a> -->

<!-- Verschachtelte interaktive Elemente -->
<button>
  <a href="/link">Link</a>                <!-- ❌ Ungültig -->
</button>

<!-- Button ohne Text/Label -->
<button>                                   <!-- ❌ Leer -->
</button>

<!-- Div/Span als Button -->
<div onclick="doSomething()">Klick</div>  <!-- ❌ Nutze <button> -->

<!-- href auf Button -->
<button href="/page">Link</button>        <!-- ❌ Funktioniert nicht -->

Häufige Fehler

1. Vergessenes type in Forms

<form>
  <!-- ❌ Wird zu type="submit" → sendet Form -->
  <button>Abbrechen</button>

  <!-- ✅ Explizit type="button" -->
  <button type="button">Abbrechen</button>
  <button type="submit">Absenden</button>
</form>

2. Button für Navigation

<!-- ❌ Falsch -->
<button onclick="window.location='/page'">
  Zur Seite
</button>

<!-- ✅ Richtig -->
<a href="/page">Zur Seite</a>

3. Disabled aber clickable

<!-- ❌ pointer-events überschreibt disabled -->
<button disabled style="pointer-events: auto;">
  Button
</button>

<!-- ✅ Richtig -->
<button disabled>Button</button>

Tipps & Tricks

Ripple-Effekt mit CSS

button {
  position: relative;
  overflow: hidden;
}

button::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.5);
  transform: translate(-50%, -50%);
  transition: width 0.6s, height 0.6s;
}

button:active::after {
  width: 300px;
  height: 300px;
}

Material Design Ripple-Effekt!

Loading-Spinner im Button

<button id="submit-btn">
  <span class="spinner" hidden>⏳</span>
  <span class="text">Absenden</span>
</button>
const btn = document.getElementById('submit-btn');
btn.addEventListener('click', async () => {
  btn.disabled = true;
  btn.querySelector('.spinner').hidden = false;
  btn.querySelector('.text').textContent = 'Lädt...';

  await submitForm();

  btn.disabled = false;
  btn.querySelector('.spinner').hidden = true;
  btn.querySelector('.text').textContent = 'Absenden';
});

Button-Gruppe mit CSS

<div class="btn-group">
  <button>Links</button>
  <button>Mitte</button>
  <button>Rechts</button>
</div>
.btn-group {
  display: flex;
}

.btn-group button {
  border-radius: 0;
  border-right: none;
}

.btn-group button:first-child {
  border-radius: 6px 0 0 6px;
}

.btn-group button:last-child {
  border-radius: 0 6px 6px 0;
  border-right: 1px solid #ccc;
}

Keyboard-Shortcuts anzeigen

<button>
  Speichern <kbd>Ctrl+S</kbd>
</button>
button kbd {
  font-size: 0.75em;
  padding: 2px 6px;
  background: rgba(0,0,0,0.1);
  border-radius: 3px;
  margin-left: 8px;
}

Double-Click Prevention

let isProcessing = false;

button.addEventListener('click', async (e) => {
  if (isProcessing) return;

  isProcessing = true;
  button.disabled = true;

  await doSomething();

  isProcessing = false;
  button.disabled = false;
});

Accessibility (Barrierefreiheit)

Aria-Label für Icon-Buttons

<!-- ❌ Kein Label -->
<button>
  <svg><!-- Icon --></svg>
</button>

<!-- ✅ Mit Label -->
<button aria-label="Einstellungen öffnen">
  <svg aria-hidden="true"><!-- Icon --></svg>
</button>

Loading States

<button
  id="btn"
  aria-busy="false"
  aria-live="polite"
>
  <span id="btn-text">Speichern</span>
</button>

<script>
btn.addEventListener('click', async () => {
  btn.setAttribute('aria-busy', 'true');
  btn.disabled = true;
  btnText.textContent = 'Speichert...';

  await save();

  btn.setAttribute('aria-busy', 'false');
  btn.disabled = false;
  btnText.textContent = 'Gespeichert!';
});
</script>

Toggle Buttons

<button
  aria-pressed="false"
  onclick="toggleMute(this)"
>
  Ton an/aus
</button>

<script>
function toggleMute(btn) {
  const pressed = btn.getAttribute('aria-pressed') === 'true';
  btn.setAttribute('aria-pressed', !pressed);
}
</script>

Fokus-Management

<!-- Nach Aktion Fokus setzen -->
<button onclick="openModal()">Modal öffnen</button>

<script>
function openModal() {
  const modal = document.getElementById('modal');
  modal.hidden = false;

  // Fokus in Modal setzen
  const closeBtn = modal.querySelector('.close-btn');
  closeBtn.focus();
}
</script>

Form-Integration

Submit-Button

<form action="/submit" method="POST">
  <input type="text" name="username" required>
  <button type="submit">Absenden</button>
</form>

Multiple Submit-Buttons

<form action="/save" method="POST">
  <textarea name="content"></textarea>

  <button type="submit" name="action" value="publish">
    Veröffentlichen
  </button>

  <button type="submit" name="action" value="draft">
    Als Entwurf speichern
  </button>
</form>

Reset-Button

<form>
  <input type="text" name="name">
  <button type="reset">Zurücksetzen</button>
</form>

⚠️ Hinweis: Reset-Buttons sind selten nützlich und können verwirren!

JavaScript-Interaktion

Event Listener

const btn = document.getElementById('my-btn');

// Click
btn.addEventListener('click', (e) => {
  console.log('Button geklickt');
});

// Submit (nur type="submit")
form.addEventListener('submit', (e) => {
  e.preventDefault(); // Verhindert Standard-Submit
  console.log('Form submit');
});

// Keyboard
btn.addEventListener('keydown', (e) => {
  if (e.key === 'Enter' || e.key === ' ') {
    e.target.click();
  }
});

Programmatisch klicken

const btn = document.getElementById('my-btn');
btn.click(); // Löst Click aus

Browser-Kompatibilität

Vollständig unterstützt in allen modernen Browsern

Besonderheiten:

  • formaction, formmethod, etc.: IE 10+
  • :focus-visible: Chrome 86+, Firefox 85+, Safari 15.4+

Zusammenfassung

Das <button>-Element ist:

  • ✅ Für Aktionen, nicht Navigation
  • ✅ Standard in Forms (type="submit")
  • ✅ Vollständig tastaturzugänglich
  • ⚠️ Benötigt type-Attribut in Forms
  • ⚠️ Icon-Buttons brauchen aria-label

Faustregel:

"Button für Aktionen, Link für Navigation!"

Typen merken:

  • submit → Formular absenden
  • reset → Formular zurücksetzen
  • button → Keine Standard-Aktion

Weiterführende Ressourcen

HTMLLektion 11 von 20
55% abgeschlossen
Lektion abgeschlossen!

Gut gemacht! 🎉

Du hast "Das <button> Element - Interaktive Schaltflächen" abgeschlossen

Artikel bewerten

0.0 (0 Bewertungen)

Bitte einloggen um zu bewerten