Damit einzelne Zeilenumbrüche im Quelltext als Leerzeichen erscheinen und Leerzeilen Absätze beginnen, musst du zuerst die Absatzstruktur erstellen und anschließend den normalen Textumbruch anwenden. Auf einem Mac kannst du dies in einer lokalen Browserseite testen; mit CSS allein lässt sich diese Unterscheidung nicht umsetzen.

Diese Anleitung richtet sich an alle, die englische Prosa für eine einfache Webseite oder eine Markdown-Vorschau vorbereiten. Ziel ist es, gut lesbare Zeilen im Quelltext beizubehalten und zugleich fließende Absätze zu erzeugen, die bei einer Änderung der Browserfensterbreite neu umbrochen werden.

Warum eine CSS-Einstellung für Leerraum nicht beide Anforderungen erfüllt

Betrachte diesen beispielhaften Quelltext. Jeder Absatz besteht aus zwei Quelltextzeilen, und eine Leerzeile trennt die Absätze:

Panel A introduces the layout
and describes the first section.

Panel B introduces another section
and describes the remaining space.

Das gewünschte Ergebnis sind zwei Absätze. Innerhalb jedes Absatzes wird der Zeilenumbruch im Quelltext zu einem Leerzeichen. Der Browser legt anschließend anhand der verfügbaren Breite fest, wo die sichtbaren Zeilenumbrüche stehen.

Bei white-space: normal werden Zeilenumbrüche im Quelltext wie andere zusammenklappbare Leerraumzeichen zusammengefasst. Das gilt auch für aufeinanderfolgende Zeilenumbrüche: Eine Leerzeile im Quelltext erzeugt keinen Absatz. Bei white-space: pre-line bleiben Zeilenumbruchzeichen als Zeilenumbrüche erhalten, einschließlich der einzelnen Umbrüche, die du zusammenführen möchtest. MDN dokumentiert dieses Verhalten in der Referenz zur Eigenschaft white-space.

Einstellung für einen Textblock Einzelner Zeilenumbruch im Quelltext Leere Quelltextzeile Für diese Aufgabe geeignet?
white-space: normal Wird mit Leerraum zusammengefasst Wird ebenfalls zusammengefasst Erst nach dem Erstellen der Absätze
white-space: pre-line Erhält den Zeilenumbruch Erhält die Umbrüche Nein
white-space: pre-wrap Erhält den Zeilenumbruch Erhält die Umbrüche Nein
Separate Absatzelemente mit white-space: normal Fließender Text innerhalb jedes Absatzes Durch eine Absatzgrenze dargestellt Ja

Das W3C beschreibt die Leerraumverarbeitung als Darstellungsvorgang, der die zugrunde liegenden Dokumentdaten unverändert lässt. Die Regeln für Segmentumbrüche hängen außerdem vom umgebenden Text ab; bei der hier verwendeten englischen Prosa ist es angemessen, einen Zeilenumbruch durch ein Leerzeichen zu ersetzen, doch diese Umwandlung gilt nicht allgemein für alle Texte. Siehe CSS Text Module Level 3.

Die praktische Lösung besteht daher aus zwei Schritten: Absätze im Quelltext erkennen und den Browser anschließend den Text layouten lassen. Der WHATWG-HTML-Standard definiert das Element p als Darstellung eines Absatzes. Der sichtbare Abstand lässt sich unabhängig davon über CSS steuern. Siehe das p-Element.

Wähle den passenden Weg für deinen Quelltext

Nutze vor Änderungen die folgende Entscheidungshilfe. Sie trennt die Interpretation des Quelltexts von der Darstellung und hilft dir so, nicht die falsche Ebene zu korrigieren.

Was du vorliegen hast Was zu tun ist
Nur Prosa in einfachem Text An Leerzeilen aufteilen, einzelne Zeilenumbrüche innerhalb jedes Absatzes zusammenführen und Absatzelemente erstellen
Markdown mit Überschriften, Listen oder Codeblöcken Einen Markdown-Parser verwenden und sein Verhalten bei weichen Zeilenumbrüchen prüfen
Vorhandenes HTML mit separaten Absatzelementen Die Leerraum- und Abstandsregeln der Absätze prüfen
Eine Seite mit expliziten Zeilenumbruch-Elementen Den Quelltext oder die Renderkonfiguration korrigieren, falls diese Umbrüche unbeabsichtigt sind
Eine Seite, die du nur ansehen kannst Einen verfügbaren Quelltext- oder Export-Workflow nutzen; für die Beispiele hier musst du das Dokument bearbeiten können

Ersetze nicht jeden Zeilenumbruch durch ein Leerzeichen, bevor du die Absätze erkannt hast: Dadurch verschwinden die Trennzeichen, anhand derer sie sich unterscheiden lassen. Verwende ebenso keine wiederholten br-Elemente als Absatzstruktur. WHATWG definiert br als Zeilenumbruch und weist darauf hin, dass es nicht dazu verwendet werden darf, thematische Gruppen innerhalb eines Absatzes zu trennen. Siehe das br-Element.

Erstelle mit TextEdit ein lokales Beispiel

Die folgende vollständige Seite benötigt TextEdit und einen Browser mit aktiviertem JavaScript. Sie enthält ein bearbeitbares Quelltextfeld und eine separate Vorschau. Externe Bibliotheken werden nicht verwendet.

  1. Öffne TextEdit und wähle Ablage > Neu und anschließend Format > In reinen Text umwandeln.
  2. Füge das vollständige Beispiel unten ein.
  3. Wähle Ablage > Sichern und nenne die Datei paragraph-demo.html.
  4. Falls du zur Dateiendung gefragt wirst, wähle „.html“ verwenden.
  5. Öffne die gespeicherte Datei in Safari oder einem anderen Desktopbrowser.

Apple beschreibt die Schritte zum Erstellen einer Klartextdatei und zum Festlegen der Dateiendung unter Mit HTML-Dokumenten in TextEdit auf dem Mac arbeiten. Wenn du die Datei zum Bearbeiten erneut öffnest, aktiviere in TextEdit unter TextEdit > Einstellungen > Öffnen und Sichern die Option HTML-Dateien als HTML-Code statt als formatierten Text anzeigen.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Paragraph flow demo</title>
  <style>
    body {
      max-width: 46rem;
      margin: 2rem auto;
      padding: 0 1rem;
      font: 1rem/1.6 system-ui, sans-serif;
    }
    label { display: block; }
    textarea {
      box-sizing: border-box;
      width: 100%;
      min-height: 12rem;
      font: 1rem/1.5 monospace;
    }
    #preview p {
      white-space: normal;
      margin: 0;
    }
    #preview p + p { margin-top: 1em; }
  </style>
</head>
<body>
  <h1>Paragraph flow demo</h1>
  <label for="source">Source text</label>
  <textarea id="source">Panel A introduces the layout
and describes the first section.

Panel B introduces another section
and describes the remaining space.</textarea>
  <h2>Preview</h2>
  <div id="preview"></div>
  <script>
    function toParagraphs(source) {
      return source.replace(/\r\n?/g, '\n')
        .split(/\n[ \t]*\n(?:[ \t]*\n)*/)
        .map(block => block
          .replace(/^[ \t\n]+|[ \t\n]+$/g, '')
          .replace(/[ \t]*\n[ \t]*/g, ' '))
        .filter(text => text.length > 0);
    }

    const source = document.getElementById('source');
    const preview = document.getElementById('preview');

    function render() {
      const paragraphs = toParagraphs(source.value).map(text => {
        const paragraph = document.createElement('p');
        paragraph.textContent = text;
        return paragraph;
      });
      preview.replaceChildren(...paragraphs);
    }

    source.addEventListener('input', render);
    render();
  </script>
</body>
</html>

Der Konverter normalisiert zunächst Wagenrücklauf- und CRLF-Zeilenenden zu LF. Anschließend teilt er den Text an jeder Zeile auf, die leer ist oder nur gewöhnliche Leerzeichen und Tabulatoren enthält. Innerhalb jedes so entstandenen Blocks ersetzt er einen verbleibenden Zeilenumbruch sowie angrenzende Leerzeichen oder Tabulatoren durch ein gewöhnliches Leerzeichen.

Dies sind ausdrücklich festgelegte Regeln für dieses Beispiel, kein allgemeiner Dokumentparser. Mehrere Leerzeilen ergeben eine Absatzgrenze. Vorangestellter und nachgestellter gewöhnlicher Leerraum wird entfernt. Eine leere Eingabe erzeugt keine Absätze. Der ursprüngliche Quelltext bleibt im Eingabefeld sichtbar, sodass du ihn mit der Umwandlung vergleichen kannst.

Der Text jedes Ausgabeabsatzes wird über textContent eingefügt. MDN dokumentiert, dass durch Zuweisung an diese Eigenschaft die untergeordneten Knoten eines Knotens durch einen Textknoten ersetzt werden. Hier wird sie nur neu erstellten, leeren Absätzen zugewiesen. Siehe Node: Eigenschaft textContent.

Die Konvertierungsfunktion bestand sechs deterministische Prüfungen in Node.js: gewöhnliche Absatzeingabe, CRLF-Eingabe, Wagenrücklauf-Eingabe, Eingabe, die nur aus Leerraum besteht, wiederholte Leerzeilen und die Beibehaltung eines geschützten Leerzeichens. Während der Vorbereitung wurde die Darstellung im Browser nicht ausgeführt; nutze die visuellen Prüfungen unten, um sie auf deinem Mac zu kontrollieren.

Prüfe Absatzgrenzen und Zeilenumbruch getrennt

Beginne mit dem bereitgestellten Beispiel. Die Vorschau sollte Panel A introduces the layout and describes the first section. als einen Absatz enthalten, gefolgt vom entsprechenden Absatz zu Panel B. Bei einem schmalen Browserfenster kann jeder Absatz mehrere sichtbare Zeilen umfassen.

Nimm nun diese gezielten Änderungen vor:

  1. Ersetze den einzelnen Zeilenumbruch nach layout durch ein Leerzeichen. Die Absatzstruktur der Vorschau sollte gleich bleiben.
  2. Stelle den Zeilenumbruch wieder her und entferne die Leerzeile zwischen den beiden Blöcken. In der Vorschau sollte daraus ein Absatz werden.
  3. Füge zwischen den Blöcken eine Leerzeile ein, die nur Leerzeichen oder Tabulatoren enthält. In der Vorschau sollten wieder zwei Absätze erscheinen.
  4. Füge dort mehrere Leerzeilen ein. Der Abstand sollte weiterhin nur dem Abstand zwischen zwei Absätzen entsprechen.
  5. Ändere die Breite des Browserfensters. Die Absatzgrenze sollte unverändert bleiben, während die Zeilen innerhalb der Absätze neu umbrochen werden.

Mit dieser Abfolge lassen sich Grenzen im Quelltext vom Umbruch im Browser unterscheiden. Im Beispiel entsteht der Absatzabstand durch die Randregel für aufeinanderfolgende Absätze. Wenn du diesen Rand änderst, verändert sich der sichtbare Abstand, ohne die Interpretation des Quelltexts zu beeinflussen.

Wenn du white-space: normal ohne diesen Konverter verwendest, bedeutet die sichtbare Verbindung nicht, dass der Zeilenumbruch im Quelltext gelöscht wurde. MDN erklärt, dass Leerraum im gewöhnlichen Textinhalt im DOM erhalten bleibt, auch wenn CSS ihn bei der Darstellung zusammenfasst. Siehe Umgang mit Leerraum.

Verwende für Markdown-Dokumente einen Markdown-Parser

Markdown bietet bereits die hier benötigte Absatzkonvention. CommonMark definiert einen Absatz als Folge nicht leerer Zeilen, die keinem anderen Blocktyp angehören; Leerzeilen trennen Absätze. Ein normaler Zeilenumbruch innerhalb eines Absatzes ist ein weicher Umbruch, den ein Renderer als Zeilenumbruch oder Leerzeichen ausgeben kann. Siehe CommonMark-Absätze und weiche Zeilenumbrüche.

Füge das Beispiel in der Quelltextansicht deines Markdown-Editors ein und prüfe die Vorschau. Wenn jeder einzelne Zeilenumbruch als sichtbarer Umbruch erscheint, prüfe die dokumentierten Darstellungsoptionen des Editors. Gehe nicht davon aus, dass jede Markdown-Anwendung dieselbe Einstellung bietet.

Wenn ein Projekt die benannte Bibliothek markdown-it verwendet, ist für die dokumentierte Option breaks standardmäßig false festgelegt. Durch die Einstellung true werden Zeilenumbrüche in Absätzen in br-Elemente umgewandelt. Mit false bleibt das gewünschte Fließtextverhalten erhalten, sofern das CSS der Ausgabe Leerraum ebenfalls zusammenfasst. Siehe MarkdownItOptions.

Explizite harte Umbrüche in Markdown müssen weiterhin berücksichtigt werden. Nach CommonMark können mindestens zwei nachgestellte Leerzeichen oder ein nachgestellter umgekehrter Schrägstrich einen harten Zeilenumbruch erzeugen. Entferne diese Markierungen nur dort, wo sie unbeabsichtigt sind. Die Regeln sind unter harte Zeilenumbrüche dokumentiert.

Führe den Klartextkonverter nicht auf ein vollständiges Markdown-Dokument aus. Er erkennt weder Überschriften und Listen noch eingerückte Codeblöcke oder Einrückungsregeln. Lass einen Markdown-Parser diese Strukturen erhalten und wende Leerraumregeln auf die daraus entstehenden Textabsätze an.

Grenzen für Browser und Textgestaltung beachten

Lass jeden Absatz mit Prosa nach Möglichkeit aus durchgehendem Text bestehen. Das Beispiel erstellt einen Textknoten pro Absatz und überlässt den Zeilenumbruch sowie die Glyphenanordnung dem Browser. Es misst keine Wörter und fügt nicht um jedes Zeichen ein eigenes Element ein.

Diese Grenze ist für die Typografie wichtig. Das W3C legt Fälle fest, in denen die Textgestaltung über Inline-Elementgrenzen hinweg fortgesetzt werden muss, und Fälle, in denen sie unterbrochen werden muss, einschließlich bestimmter Änderungen bei Abständen und Ausrichtung. Füge keine unnötigen Inline-Boxen hinzu, nur um Zeilenpositionen zu steuern. Siehe Textgestaltung über Elementgrenzen hinweg.

Verwende den Konverter nur, wenn jeder einzelne Zeilenumbruch im Quelltext eine redaktionelle Zeilenaufteilung ist. Wenn ein Zeilenumbruch absichtlich Beschriftungen trennt oder innerhalb eines Wortes auftritt, ändert das Zusammenführen mit einem Leerzeichen den Inhalt. Das Beispiel behandelt zudem eine Zeile mit einem geschützten Leerzeichen als Inhalt und nicht als leeren Trenner; MDN unterscheidet geschützte Leerzeichen von gewöhnlichem zusammenklappbarem Dokumentleerraum unter Umgang mit Leerraum.

Bei englischer Prosa solltest du zuerst Absatzgrenzen festlegen und innerhalb der Absätze den normalen Browserumbruch zulassen. Das lokale Beispiel macht diese Regel überprüfbar: Der Quelltext behält seine bearbeitbaren Zeilen, die Vorschau enthält echte Absätze und beim Ändern der Fensterbreite ändert sich nur der sichtbare Zeilenumbruch.

Quellen