Wieder haben mich viele neue Fragen zu HTML5, CSS3 und JavaScript über die diversen Kanäle erreicht. Dass es nicht zu mehr Blogposts kommt, ist allein meine Schuld … aber genug gejammert, ran an die neusten Leserfragen!

Unterschied width/flex-basis

Was ist bei einem Flexbox-Layout der Unterschied zwischen width und flex-basis? Gibt es überhaupt einen?

Beim Bau eines 0815-Spaltenlayouts ist es so gut wie egal, ob man width oder flex-basis verwendet – bei der einfachen Anordnung von Boxen nebeneinander führen beide Eigenschaften zum gleichen Ergebnis. Allerdings gibt es durchaus Unterschiede, die je nach Use Case durchaus ins Gewicht fallen können:

  • Vielleicht offensichtlich, aber dennoch erwähnenswert: flex-basis funktioniert nur im Flexbox-Kontext, width greift hingegen immer. Wenn man eine wiederverwertbare Komponente gestaltet, die mal mit und mal ohne Flexbox verwendet werden soll, ist das ein Argument für width.
  • Der Effekt von flex-basis ist von der gewählten flex-direction abhängig. Während width immer die horizontale Ausdehnung eines Elements steuert, kann flex-basis, wenn flex-direction auf column oder column-reverse steht, für die Höhe zuständig sein.
  • Während width auch bei absolut positionierten Elementen funktioniert, ist das bei Flex-Items nicht der Fall
  • Die praktische Abkürz-Eigenschaft flex fasst flex-basis mit flex-shrink und flex-growzusammen. Für width gibt es nichts Entsprechendes.

Hier eine kleine Demo der Gemeinsamkeiten und Unterschiede.

Semikolons nach Funktionsdeklarationen

Warum muss ich in JavaScript bei Funktionsdeklarationen kein Semikolon verwenden? Ich weiß Semikolons sind optional, aber bei Funktionsdeklarationen sehe ich so gut wie nie Semikolons. Warum ist das so?

Die ECMAScript-Spezifikationen verlangen tatsächlich nach Funktionsdeklarationen kein Semikolon (wenn eins da ist, stört es aber nicht). Zur Einordnung: das hier ist eine Funktionsdeklaration …

function foo(){
  return 42;
}

… und im Vergleich dazu ein Funktionsausdruck, nach dem man (wenn man mal die automatische Semikolon-Einfügung ignoriert) ein Semikolon haben sollte:

var foo = function(){
  return 42;
};

Und warum ist das so? Semikolons trennen in JavaScript Statements voneinander. Funktionsdeklarationen sind aber keine Statements, sondern fallen in die Kategorie Declaration. Der beobachtbare Hauptunterschied ist, dass Funktionsdeklarationen evaluiert werden, bevor das Script tatsächlich ausgeführt wird. Das kann man daran erkennen, dass Funktionsdeklarationen aufgerufen werden können, bevor sie im Code definiert werden, was mit einem Funktionsausdruck nicht klappt:

// Function Declaration
foo(); // Klappt
function foo(){
  window.alert(23);
}

// Function Expression
bar(); // Klappt nicht
var bar = function(){
  window.alert(42);
};

Lange Rede, kurzer Sinn: der Job, den Semikolons in JavaScript machen, wird von Funktionsdeklarationen nicht benötigt.

Formulardaten lokal speichern

Ich möchte in ein Formular eingegebene Daten lokal speichern. Muss ich dafür ein jQuery-Plugin benutzen oder geht das auch mit HTML5-Bordmitteln?

Mit FormData gibt es eine recht einfache API um die eigegebenen Daten aus einem Formular zu extrahieren. Das von new FormData(someFormElement) zurückgegebene Element hat eine entries() Methode, die einen Iterator über die Name-Wert-Paare der Formulardaten zurückgibt – und von da aus ist der Weg zum speicherbaren JSON nicht mehr weit:

document.querySelector("input[value=Speichern]").addEventListener("click", () => {
  // Iterator mit [name, value]
  const data = new FormData(document.querySelector("form")).entries();
  // Daten als Objekte in einem Array
  const serialized = Array.from(data, ([name, value]) => ({ name, value }));
  // JSON, bereit zum Speichern in DOM Storage!
  const json = JSON.stringify(serialized);
  console.log(json);
});

So einfach kann es sein! Wichtig ist: FormData-Objekte können ohne Serialisierung direkt von XMLHttpRequest.send() verschickt werden und die IndexedDB kann zumindest die aus dem Iterator erzeugten Arrays speichern, ganz ohne JSON.

Warum funktioniert mein Custom Error nach dem Submit-Event nicht?

Ich habe ein Formular gebaut, das beim Submit-Event ein paar Dinge validiert und im Fehlerfall mit setCustomValidity() HTML5-Validierungsfehler auf den Feldern auslösen soll. Das scheint aber in keinen Browser zu funktionieren. Was ist da los?

Wenn man mit setCustomValidity() Felder als ungültig markieren möchte, muss man das vor dem Submit-Event erledigen. Der Sinn von setCustomValidity() ist das Festlegen des Fehler-Zustandes eines Feldes, nicht an Anzeigen der Fehlermeldung– das erledigt der Browser beim bzw. kurz vor dem Abschicken des Formulars selbst. Ein kleiner Auszuug aus dem Form submission algorithm von HTML5:

When a form element form is submitted from an element submitter (typically a button), optionally with a submitted from submit() method flag set, the user agent must run the following steps:

  1. If [...] the constraint validation concluded that there were invalid fields and probably informed the user of this [...] fire a simple event named invalid at the form element and then abort these steps.
  2. [...] then fire a simple event [...] named submit, at form.

Man sieht: die Validierung findet vor dem Submit-Event statt. Deshalb sollte sollte setCustomValidity() dann passieren, wenn sich der Inhalt eines Feldes ändert (z.B. bei change- oder keyup-Events).

Weitere Fragen?

All diese Fragen wurden mir per E-Mail oder Twitter gestellt und auch eure Fragen zu HTML(5), CSS(3), JavaScript und anderen Webtechnologien beantworte ich gerne! Einfach über einen der genannten Kanäle anschreiben oder gleich das komplette Erklärbären-Paket kommen lassen.