# Konfiguration: Witwen, Waisen und Spaltenausgleich

> Die Regeln, die Zeilen und Blöcke über einen Spaltenumbruch hinweg zusammenhalten, und die Hebel, mit denen jede Spalte auf gleicher Höhe endet

- HTML-Fassung: https://postext.dev/de/docs/configuration-page-flow
- Zuletzt aktualisiert: 2026-10-16
- Lesezeit: 21 min
- Andere Sprachen: [en](https://postext.dev/en/docs/configuration-page-flow.md), [es](https://postext.dev/es/docs/configuration-page-flow.md), [ca](https://postext.dev/ca/docs/configuration-page-flow.md), [fr](https://postext.dev/fr/docs/configuration-page-flow.md), [it](https://postext.dev/it/docs/configuration-page-flow.md), [pt](https://postext.dev/pt/docs/configuration-page-flow.md), [zh](https://postext.dev/zh/docs/configuration-page-flow.md), [ja](https://postext.dev/ja/docs/configuration-page-flow.md), [ar](https://postext.dev/ar/docs/configuration-page-flow.md)

## Kurz gesagt

Diese Seite erklärt, wie Postext entscheidet, wo eine Spalte oder eine Seite endet. Eine einzelne Zeile eines Absatzes sollte nicht allein oben oder unten in einer Spalte stehen, und eine Überschrift sollte nicht ohne ihren Text bleiben. Diese Regeln können eine Spalte kürzer machen als die anderen. Dann nimmt Postext in einer festen Reihenfolge kleine Änderungen vor, damit alle Spalten auf derselben Höhe enden. Die Seite führt jede Regel und jede Änderung auf und zeigt, wie Sie sehen, welche gegriffen hat.

## Waisen, Witwen, zu kurze Ausgangszeilen und Regeln zum Zusammenhalten

Die Mechanik hinter diesen Strafpunkten erklärt [Silbentrennung und Blocksatz](https://postext.dev/de/docs/justification.md). Dieser Abschnitt ist die Referenz der Schlüssel von `bodyText`, die sie steuern.

Über Silbentrennung und Abstandsgrenzen hinaus stellt die Konfiguration des Fließtexts die weichen Regeln bereit, die strukturell ungeschickte Absatzumbrüche verhindern. Sie alle gehen als Strafpunkte in den Zeilenumbruch-Algorithmus von Knuth-Plass ein – sie lenken das Layout zu sauberen Umbrüchen, ohne je eine harte Regel zu erzwingen. Setzen Sie die Werte `*Penalty` auf `0`, um eine von ihnen praktisch abzuschalten.

| Eigenschaft | Typ | Standard | Beschreibung |
| --- | --- | --- | --- |
| `avoidOrphans` | `boolean` | `true` | Wirkt dem entgegen, dass ein Absatz mit weniger als `orphanMinLines` Zeilen oben in der nächsten Spalte endet. Auf einem Zeichenraster (`cjk.grid`) in der Region `japan` ist der Standard `false`. |
| `orphanMinLines` | `number` | `2` | Mindestzahl der Zeilen oben in der nächsten Spalte, wenn ein Absatz geteilt wird. Nur wirksam, wenn `avoidOrphans` `true` ist. |
| `orphanPenalty` | `number` | `1000` | Strafpunkte, die hinzukommen, wenn die Bedingung gegen Waisen verletzt wird. Höhere Werte lenken den Algorithmus stärker gegen Waisen; `0` schaltet die Strafe ab. |
| `avoidOrphansInLists` | `boolean` | `true` | Mit `true` erhalten auch Listenpunkte den Schutz vor Waisen (nicht nur Absätze). Nur wirksam, wenn `avoidOrphans` `true` ist. |
| `avoidWidows` | `boolean` | `true` | Wirkt dem entgegen, dass ein Absatz mit weniger als `widowMinLines` Zeilen unten in der aktuellen Spalte beginnt. Auf einem Zeichenraster (`cjk.grid`) ist der Standard `false`: Die Seite fasst die Zeilen, die ihr Raster zählt. |
| `widowMinLines` | `number` | `2` | Mindestzahl der Zeilen unten in der aktuellen Spalte, wenn ein Absatz geteilt wird. Nur wirksam, wenn `avoidWidows` `true` ist. |
| `widowPenalty` | `number` | `1000` | Strafpunkte, die hinzukommen, wenn die Bedingung gegen Witwen verletzt wird. `0` schaltet die Strafe ab. |
| `avoidWidowsInLists` | `boolean` | `true` | Mit `true` erhalten auch Listenpunkte den Schutz vor Witwen. Nur wirksam, wenn `avoidWidows` `true` ist. |
| `shortListSplit` | `'allow' \| 'warn' \| 'avoid'` | `'allow'` | Eine kurze Liste, die zwischen zwei Spalten oder Seiten geteilt wird: eine Liste mit bis zu `shortListMaxItems` Punkten im laufenden Text, etwa eine mit drei Punkten, aufgeteilt in 1 + 2. `avoidOrphansInLists` und `avoidWidowsInLists` halten die Zeilen eines Punkts zusammen; diese Regel hält die Punkte einer Liste zusammen. `'allow'` teilt eine solche Liste wie jede andere dort, wo die Spalte endet. `'warn'` setzt sie ebenso und meldet jede geteilte Liste (eine Warnung `shortListSplit`, siehe [Warnungen im Dokument](https://postext.dev/de/docs/configuration-programmatic-usage.md#warnungen-im-dokument)). `'avoid'` setzt die Liste ungeteilt: Passt sie nicht unter das, was die Spalte fasst, eröffnet sie die nächste Spalte, und die Überschriften direkt über ihr und die Doppelpunktzeile, die sie einleitet (`keepColonWithList`), gehen mit. Eine Liste, die höher als eine leere Spalte ist, wird wie jede andere geteilt und gemeldet. Listen in einem `:::callout` folgen den eigenen Teilungsregeln des Kastens, und die Einträge von `:::toc` und `:::index` sind keine Listen. Seit postext 1.28. |
| `shortListMaxItems` | `number` | `3` | Die Höchstzahl an Punkten, bis zu der eine Liste für `shortListSplit` als kurz gilt, die Punkte ihrer verschachtelten Listen eingeschlossen. Eine ganze Zahl, mindestens 1. Seit postext 1.28. |
| `avoidRunts` | `boolean` | `true` | Wirkt dem entgegen, dass Absätze mit einer sehr kurzen letzten Zeile enden – einer *zu kurzen Ausgangszeile*, z. B. einem einzelnen kurzen Wort. Mit `optimalRagged` auch im Flattersatz. Ein chinesischer, japanischer oder koreanischer Absatz endet nicht auf einer Zeile mit einem einzigen Zeichen, allein oder mit seinen schließenden Zeichen (孤字): Die Zeile darüber gibt ihr ihr letztes Zeichen, wenn diese Zeile sich noch innerhalb der Laufweitengrenze in Blocksatz bringen lässt. Eine links, rechts oder zentriert gesetzte Zeile gibt das Zeichen ebenfalls ab und steht ein Zeichen kürzer; mit `cjk.grid.fullLines` (Manuskriptpapier) behält sie jedes Kästchen, und der Absatz darf auf einem Zeichen enden. |
| `runtMinCharacters` | `number` | `20` | Schwelle für die letzte Zeile eines Absatzes, gezählt in Wortzwischenräumen, nicht in Buchstaben: Die Zeile ist zu kurz, wenn sie schmaler als `runtMinCharacters × normalSpaceWidth` Pixel ist. Ein Wortzwischenraum misst in den meisten Textschriften ein Viertel bis ein Drittel Geviert, etwa einen halben Kleinbuchstaben, sodass der Standard 20 letzte Zeilen unter 4 bis 7 em erfasst – grob 8 bis 12 Buchstaben. Um die letzten Zeilen unter etwa N Buchstaben zu erfassen, setzen Sie den Wert auf etwa 2 × N. |
| `runtPenalty` | `number` | `1000` | Äquivalente Schlechtigkeit (badness), die in die quadrierte Strafpunktformel von Knuth-Plass eingespeist wird (auf derselben Skala wie die *badness* einer Zeile, die bei 10000 sättigt). `0` schaltet die Strafe ab. |
| `gradedRuntPenalty` | `boolean` | `false` | Staffelt die Strafe für zu kurze Ausgangszeilen danach, wie kurz die letzte Zeile ausfällt: Eine letzte Zeile der Breite *w* unter der Schwelle *t* kostet `runtPenalty × (1 − w / t)` statt der ganzen Strafe. Ein Ausgang aus zwei Wörtern kostet dann weniger als einer aus einem Wort, und der Umbruch zieht ein Wort hinunter, wenn eine Zeile darüber es entbehren kann („…sallies of“ / „our minds.“ statt „…sallies of our“ / „minds.“). Standardmäßig aus: Jede zu kurze Ausgangszeile kostet gleich viel, und der Umbruch behält die engeren Zeilen darüber. |
| `avoidRuntsInLists` | `boolean` | `true` | Mit `true` erhalten auch Listenpunkte die Strafe für zu kurze Ausgangszeilen. Nur wirksam, wenn `avoidRunts` `true` ist. |
| `tightenRunts` | `boolean` | `true` | Konnte die Strafe eine zu kurze Ausgangszeile nicht vermeiden, wird der Absatz stattdessen eine Zeile kürzer gesetzt: Die Wortabstände werden enger (nie unter `minWordSpacing`), und reicht das allein nicht, um die Zeile aufzunehmen, kommt eine kleine negative Laufweite hinzu. Ein kürzerer Satz wird verworfen, und die zu kurze Ausgangszeile bleibt, wenn er eine Blocksatzzeile über `maxWordSpacing` hinaus dehnen würde oder, wenn der Absatz bereits eine lockerere Blocksatzzeile hat, über diese hinaus, oder wenn er mehr Zeilen im Flattersatz (über das 3-Fache des normalen Leerzeichens hinaus) setzen würde, als der Absatz hatte. Die Wortabstände im Flattersatz behalten ihre Breite, dort wirkt also nur die Laufweite mit. Erfordert `optimalLineBreaking` und `avoidRunts` (und für Flattersatz `optimalRagged`). |
| `maxRuntTracking` | `number` | `10` | Höchste Laufweite, die die Korrektur einer zu kurzen Ausgangszeile nehmen darf, in Tausendstel eines Gevierts (die InDesign-Einheit: 10 = 0,01 em pro Zeichen), angewandt als Verengung. `0` überlässt die Korrektur allein dem Wortabstand. |
| `slackWeight` | `number` | `10` | Gewicht der quadrierten Kosten für „ungenutzten Spaltenraum“. Höhere Werte lassen das Layout eng gefüllte Spalten bevorzugen; `0` schaltet den Druck durch ungenutzten Raum ganz ab. |
| `keepColonWithList` | `boolean` | `true` | Endet ein Absatz mit einem Doppelpunkt, der unmittelbar eine Liste einleitet, bleibt die letzte Zeile mit dem Doppelpunkt mit der Liste verbunden: Ließe das Platzieren des Absatzes keinen Raum, damit der erste Listenpunkt in derselben Spalte bzw. auf derselben Seite beginnt, wird die letzte Zeile (oder der ganze Absatz, wenn er nur eine Zeile hat) zusammen mit der Liste in die nächste Spalte verschoben. Wie viel Raum genügt, legt `colonListRoom` fest. Würde diese Regel den ganzen Absatz verschieben und steht direkt davor in der Spalte eine Folge von Überschriften, werden diese ebenfalls mitgezogen, damit `headings.keepWithNext` weiter gilt. |
| `colonListRoom` | `'item' \| 'line'` | `'item'` | Der Raum, den `keepColonWithList` unter der Doppelpunktzeile verlangt. `'item'`: was die Regeln gegen Waisen und Witwen in Listen vom ersten Punkt am Fuß der Spalte übrig ließen, eine Zeile, wenn er dort geteilt werden darf, der ganze Punkt, wenn sie ihn zusammenhalten (etwa ein zweizeiliger Punkt). `'line'`: eine Zeile, wie bis postext 1.4; ein erster Punkt, den diese Regeln zusammenhalten, geht dann allein in die nächste Spalte weiter und lässt die Doppelpunktzeile am Fuß zurück. Eine vor `configVersion` 6 gespeicherte Konfiguration in einem Buch, das eine Liste mit einem Doppelpunkt einleitet, wird mit `'line'` gelesen (siehe [Pakete, die postext 1.4 oder früher geschrieben hat](https://postext.dev/de/docs/configuration-bundles.md#pakete-die-postext-14-oder-früher-geschrieben-hat)). Jeder andere Wert wird als `'item'` gelesen. |
| `hyphenateAcrossColumns` | `boolean \| 'withinPage'` | `true` | Erlaubt, dass eine Spalte oder eine Seite auf einem getrennten Wort endet (*Silbentrennung über Spalten hinweg* in InDesign). `false` bricht den Absatz, der den Spaltenumbruch überquert, erneut um, sodass seine letzte Zeile in der Spalte auf einem ganzen Wort endet; die Wortabstände der Zeilen darüber nehmen den Unterschied auf, innerhalb von `maxWordSpacing` und `minWordSpacing`. Es ist eine Vorliebe: Wo kein Umbruch innerhalb dieser Grenzen es vermeidet, bleibt der Trennstrich. Die Option probiert jeden Spaltenumbruch eines Absatzes: den ersten und die späteren, die dort liegen, wo eine volle Spalte endet, in einem neuen Umbruch; und einen späteren Umbruch, der woanders liegt (eine gehaltene Witwe, eine ausgeglichene Schnittkante eines Bands), in einem weiteren ab dieser Spalte, der die bereits in den vorigen Spalten gesetzten Zeilen an ihren Umbrüchen lässt und nur den Rest umbricht. `'withinPage'` schützt die Zeilen, die eine Seite schließen, und keine anderen: Ein Wort darf zwischen zwei Spalten einer Seite getrennt werden, und die letzte Zeile einer Seite endet auf einem ganzen Wort, wo immer die Grenzen es zulassen. Die Option ändert weniger Zeilen als `false`, was bei drei oder mehr Spalten zählt, wo zwei von drei Spaltenenden innerhalb der Seite liegen; in einer einzigen Spalte ergeben beide Werte dieselben Zeilen. Eine Spalte schließt ihre Seite, wenn keine spätere Spalte der Seite Text aufnimmt: Eine für Gleitobjekte freigehaltene Seitenspalte tut es nicht, ebenso wenig eine Spalte, die eine Tabelle oder Abbildung gefüllt hat. Kastentexte sind nicht betroffen. Mit `optimalRagged` wird ein Absatz im Flattersatz auf dieselbe Weise neu umbrochen: Seine Wortabstände behalten ihre Breite, sodass sich nur die Enden seiner Zeilen verschieben. Jeder neue Umbruch misst den Absatz noch einmal, ein Buch mit vielen Trennstrichen am Spaltenende wird also etwas langsamer gesetzt. Erfordert `optimalLineBreaking` und für Flattersatz `optimalRagged`. |
| `paragraphContainerSpacing` | `'collapse' \| 'add'` | `'collapse'` | Der Abstand unter einem Container `:::paragraphs`, der mit einem Absatz schließt, zwischen diesem Absatz und dem Block danach (siehe [Der Container `:::paragraphs`](https://postext.dev/de/docs/configuration-styles.md#der-container-paragraphs)). `'collapse'`: der größere Wert aus `spaceBetween` und `marginBottom` des Formats und dem Absatzabstand des Texts um den Container (eine Zeile mit `paragraphSpacing`; in einem Kasten der des Kastens), zusammengeführt mit dem Abstand, den der nächste Block über sich hält, wie zwischen zwei Absätzen des laufenden Texts: Eine Überschrift unter einem Literaturverzeichnis steht ihr eigenes `marginTop` darunter, nicht diesen Rand plus den Abstand der Einträge. `'add'`: wie bis postext 1.4 wird der Abstand des Formats allein unter die letzte Zeile gesetzt, bevor auf das Raster eingerastet wird, der eigene obere Abstand des nächsten Blocks darunter addiert und der Absatzabstand weggelassen, sodass der Absatz nach dem Container ihm näher stehen konnte als jedem anderen. Eine vor `configVersion` 8 gespeicherte Konfiguration, die ein Absatzformat deklariert, in einem Buch mit einem solchen Container, wird mit `'add'` gelesen (siehe [Pakete, die postext 1.4 oder früher geschrieben hat](https://postext.dev/de/docs/configuration-bundles.md#pakete-die-postext-14-oder-früher-geschrieben-hat)). Ein negatives `marginBottom` zieht den nächsten Block in jedem Fall hinauf. Ein Absatzformat kann für seine Container eine eigene Regel setzen (`containerSpacing`, seit postext 1.28). |

**Zu kurze Ausgangszeilen.** Eine zu kurze Ausgangszeile hat ein Absatz, dessen letzte Zeile zu kurz ist, um als richtige Textzeile zu wirken – typischerweise ein oder zwei kurze Wörter, die am Ende eines Absatzes gestrandet sind. Da die Prüfung auf der Länge der Zeile in Pixeln relativ zur normalen Leerzeichenbreite beruht, passt sich `runtMinCharacters` automatisch der aktuellen Schriftgröße an. Ein kurzes Wort, das optisch breiter als `runtMinCharacters × spaceWidth` ist, ist in Ordnung; ein Wort, das schmaler ist (oder wirklich allein steht), zieht die Strafe auf sich. Die Schwelle zählt Wortzwischenräume, die etwa halb so breit wie Buchstaben sind: Der Standard 20 entspricht einer letzten Zeile von grob 8 bis 12 Buchstaben. Jede zu kurze Ausgangszeile kostet die ganze Strafe, sodass der Umbruch von zwei Ausgängen unter der Schwelle die engeren Zeilen darüber behält; `gradedRuntPenalty` bewertet jeden stattdessen nach seinem Fehlbetrag, und der längere Ausgang gewinnt. Für mathematisch Interessierte: Beim Standardwert 1000 für `runtPenalty` überwiegt das Vermeiden einer zu kurzen Ausgangszeile jede andere Wahl der Umbrüche, die eine Dehnung des Wortabstands bis etwa r≈2,15 erfordert.

**Weich, nicht hart.** Keine dieser Regeln kann einen Umbruch *verhindern* – die Engine liefert immer ein Layout. Es sind Strafpunkte: Der Algorithmus wägt Schlechtigkeit, Trennkosten, Gleichmäßigkeit der Fitness-Klassen und diese strukturellen Strafen in einer einzigen globalen Optimierung gegeneinander ab und wählt die Umbrüche mit den geringsten Gesamtkosten. Brauchen Sie eine härtere Garantie, erhöhen Sie die Strafe; liest sich ein bestimmtes Dokument mit einer gelockerten Strafe besser, senken Sie sie.

## Spaltenausgleich

Verlage erwarten, dass jede Spalte oben auf der Seite beginnt und bündig mit ihrem Fuß endet. Umbruchregeln (Schutz vor Waisen und Witwen, mit ihrem Text zusammengehaltene Überschriften, unteilbare Abbildungen) hinterlassen naturgemäß kurze Spalten – eine oder mehrere leere Zeilen des Grundlinienrasters am Fuß. Ist der Ausgleich aktiviert, tut die Engine, was ein Setzer täte, und setzt ihre Hebel in redaktioneller Rangfolge ein:

1. **Ein Kasten, der die Spalte schließt** – ein Kasten am Ende einer kurzen Spalte wird um genau den Raum unter seinem Fuß nach unten geschoben, sodass seine Unterkante auf dem letzten Rasterplatz der Seite landet, auf gleicher Höhe mit der letzten Zeile der Spalte daneben. Er nimmt diesen Raum auch dann, wenn er kleiner als eine Zeile ist, solange nichts in eine andere Spalte rückt. Standardmäßig läuft er vor jedem anderen Hebel und nimmt die ganze Lücke, sodass ein Kasten, der den Absatz darüber kommentiert, mehrere Zeilen unter ihm landen kann; `closingBox: 'last'` lässt die Überschriften, die Listenenden und die übrigen Abstandshebel zuerst die ganzen Zeilen nehmen und dem Kasten nur, was sie übrig lassen, und `closingBox: 'off'` bewegt ihn nie.
2. **Bilder mit Sicherheitsbereich** – ein Bild mit Sicherheitsbereich (`Resource.safeArea`, siehe [Dokumentformat › Sicherheitsbereich](https://postext.dev/de/docs/document-format-resources.md#sicherheitsbereich)), das inline in der kurzen Spalte steht oder an ihrem Kopf oder Fuß allein über dieser Spalte gleitet, wächst um ganze Rasterzeilen, beschnitten innerhalb seines Sicherheitsbereichs, bis die Spalte voll ist oder der Beschnitt den Sicherheitsbereich erreicht. Ein höheres Bild hinterlässt kein Loch auf der Seite, daher läuft dieser Hebel, bevor Abstand hinzugefügt wird; ein Gleitobjekt am Kopf einer Spalte auf einer Seite oder in einem Band, dessen Spaltenköpfe auf gleicher Höhe bleiben (siehe unten), wächst nicht. Gespeichert als `flexFigure`. Er hat keine eigene Einstellung: Nur ein Bild, dessen Ressource einen Sicherheitsbereich markiert, kann wachsen.
3. **Überschriften** – ganze Rasterzeilen werden dem oberen Rand der Überschriften in der kurzen Spalte hinzugefügt. Werden mehrere Zeilen gebraucht und enthält die Spalte mehrere Überschriften, werden die Zeilen auf sie verteilt, wobei die wichtigste Überschrift stets den größten Anteil erhält (eine `h2` erhält mehr als eine `h3`). Überschriften ganz oben in einer Spalte erhalten nie zusätzlichen Abstand, damit Spalten weiter am Seitenkopf beginnen – außer einer Überschrift direkt unter einer Abbildung oder Tabelle, die ihre Spalte auf einer weiterlaufenden Seite anführt: Der Raum kommt über diese Überschrift, unter die Abbildung. Eine Überschrift nimmt auf diese Weise höchstens `maxLinesBeforeLoose` Zeilen (standardmäßig zwei), bevor die Hebel weiter unten probiert werden, und ihre weiteren Zeilen bis `maxLinesPerHeading` nur, wenn jene nichts mehr zu geben haben.
4. **Listenenden** – können die Überschriften nicht die ganze Lücke aufnehmen, wird dort eine Rasterzeile eingefügt, wo eine Liste oder Aufzählung endet (Abstand nach einer Liste wirkt natürlich), begrenzt pro Listenende.
5. **Unter Formeln, Kästen und Abbildungen** – dann kommt eine Rasterzeile unter eine abgesetzte Formel oder einen Kasten, nach dem der Text weiterläuft (`stretchAfterDisplays`; sie wirkt wie der eigene Rand des Elements), und unter eine Abbildung oder Tabelle, die die Spalte anführt (`stretchAfterFloats`, begrenzt durch `maxLinesAfterFloat`).
6. **Lockere Absätze** – als letztes Mittel wird ein Absatz der Spalte eine Zeile länger neu umbrochen (`\looseness=+1` in TeX), wobei der längste Absatz gewählt wird, damit sich der zusätzliche Wortabstand unsichtbar verteilt. Die lockere Lösung wird nur angenommen, wenn jede Zeile **unter `bodyText.maxWordSpacing`** bleibt – der Grauwert überschreitet nie die Grenze, die Sie bereits eingestellt haben. Erfordert `bodyText.optimalLineBreaking`.

Auf einem Zeichenraster (`cjk.grid`, siehe [Chinesischer Satz › Das Zeichenraster](https://postext.dev/de/docs/chinese-layout.md#das-zeichenraster)) steht jedes Zeichen in einer Zelle von einem Geviert Breite und jede Zeile im Zeilenschritt des Rasters, der auch das Grundlinienraster ist. Der Ausgleich ist dort standardmäßig aus, wie im vertikalen Text: Eine Seite, die Zeile für Zeile auf einem Raster gesetzt ist, so wie GB/T 9704 22 Zeilen zu 28 Zeichen zählt, lässt eine kurze Spalte kurz. Eine Konfiguration mit `enabled: true` erhält Hebel, die das Raster einhalten: Überschriften, Listenenden, abgesetzte Elemente und Abbildungen nehmen ganze Rasterzeilen, sodass sich der Text darunter um ganze Zeilen verschiebt, und `gridLines: 'off'` hält diese für einen Standard heraus, der keine leere Zeile herzugeben hat. Ein chinesischer oder japanischer Absatz läuft nur dann eine Zeile länger, wenn sich keine Lücke zwischen zwei seiner Zeichen über `maxTracking` hinaus dehnt, und nimmt keine Laufweite auf seine Buchstaben: Eine Zeile, der ein Zeichen fehlt, verteilt ein Geviert auf ihre Lücken, weit über den Standard von 0,01 em hinaus, sodass der Hebel für lockere Absätze auf einem Raster aus ganzen Zellen meist nichts findet. Der Kasten, der eine Spalte schließt, und die Bilder mit Sicherheitsbereich liegen bewusst außerhalb des Rasters und funktionieren wie überall.

Die letzte Spalte einer Seite wird nur ausgeglichen, wenn die Seite natürlich in die nächste weiterläuft – die Schlussseite eines Kapitels endet zu Recht kurz. Eine solche Seite und ein von `trailing` auf gleicher Höhe abgeschnittenes Schlussband halten auch ihre Spaltenköpfe auf gleicher Höhe: Unter einer Abbildung oder Tabelle, die eine ihrer Spalten anführt, wird keine Zeile hinzugefügt (der Hebel nach Gleitobjekten), und eine Überschrift oder ein Kasten, der unter einer solchen Abbildung eine Spalte eröffnet, bleibt an ihrem Kopf, was auch immer `stretchAfterFloats` sagt, ebenso wie die Überschrift direkt unter einem Auftakt mit `span: 'page'` in dessen eigener Spalte, sodass eine Spalte nie tiefer beginnt als die daneben, nur damit die Füße fluchten.

| Eigenschaft | Typ | Standard | Beschreibung |
| --- | --- | --- | --- |
| `enabled` | `boolean` | `true` | Ob die Spaltenfüße ausgeglichen werden. Standardmäßig aus in vertikalem Text (`layout.writingMode: 'vertical-rl'`) und auf einem Zeichenraster (`cjk.grid.enabled`, seit postext 1.25); `true` schaltet ihn auch dort ein. |
| `maxLinesPerHeading` | `number` | `4` | Höchstzahl zusätzlicher Rasterzeilen, die über einer einzelnen Überschrift eingefügt werden dürfen. |
| `maxLinesBeforeLoose` | `number` | `2` | Rasterzeilen, die eine Überschrift nehmen darf, bevor die Hebel nach ihr probiert werden: die Listenenden, die Formeln und Kästen, die Abbildungen und die lockeren Absätze. Ihre weiteren Zeilen bis `maxLinesPerHeading` erhält eine Überschrift nur, wenn jene nichts mehr zu geben haben, sodass eine Seite mit einer Überschrift nicht vier Zeilen über ihr aufreißt, während ihre Absätze eine Zeile länger laufen könnten. Ein Wert ab `maxLinesPerHeading` gibt den Überschriften zuerst alle ihre Zeilen, wie bis postext 1.27; `0` probiert die anderen Hebel, bevor irgendeine Zeile über eine Überschrift kommt. Seit postext 1.28; früher gespeicherte Dokumente behalten die alte Reihenfolge (`pinLegacyLooseOrder`). |
| `stretchAfterLists` | `boolean` | `true` | Erlaubt zusätzliche Rasterzeilen am Ende einer Liste, wenn Überschriften nicht die ganze Lücke aufnehmen können. |
| `maxLinesAfterList` | `number` | `1` | Höchstzahl zusätzlicher Rasterzeilen nach einem einzelnen Listenende. |
| `stretchAfterDisplays` | `boolean` | `true` | Erlaubt in der kurzen Spalte nach dem Hebel für Listenenden eine zusätzliche Rasterzeile unter einer abgesetzten Formel und unter einem Kasten: Der Block danach rückt eine Zeile nach unten. Setzen Sie die Option auf `false`, um den Abstand unter Formeln und Kästen so zu lassen, wie ihre eigenen Ränder ihn setzen; die Lücke geht an die Hebel nach diesem weiter, und die Spalte endet kurz, wenn sie sie nicht schließen. Seit postext 1.28. |
| `stretchAfterFloats` | `boolean` | `true` | Erlaubt nach dem Hebel für Listenenden zusätzliche Rasterzeilen unter einer Abbildung oder Tabelle, die die kurze Spalte anführt (ein Gleitobjekt oben), sodass der Text darunter nach unten rückt, statt dass die Spalte kurz endet. Nie auf einer Seite, die nicht weiterläuft (der Schlussseite eines Kapitels), und nie in einem von `trailing` auf gleicher Höhe abgeschnittenen Schlussband: Dort bleiben die Spaltenköpfe auf gleicher Höhe, und die letzte Spalte darf eine Zeile kürzer enden. Der erste Block unter der Abbildung kann der Rest eines Absatzes sein, der auf der vorigen Seite begonnen hat: Er rückt trotzdem nach unten, um die Zeile, die die Umbruchregeln am Fuß der Spalte freigelassen haben (eine Zeile, die die Witwenregel leer gehalten hat, oder ein Absatzabstand ohne Platz für Text danach). Setzen Sie die Option auf `false`, um den Text direkt unter der Abbildung zu halten. Unter einem Gleitobjekt über mehrere Spalten bewegen sich die Spalten gemeinsam oder gar nicht, siehe `stretchAfterWideFloats`. |
| `maxLinesAfterFloat` | `number` | `1` | Höchstzahl zusätzlicher Rasterzeilen unter einem einzelnen Gleitobjekt oben. |
| `stretchAfterWideFloats` | `'flush' \| 'always'` | `'flush'` | Unter einer Abbildung oder Tabelle, die über zwei oder mehr Textspalten steht. Mit `'flush'` rückt eine Spalte darunter nur dann nach unten, wenn jede Textspalte unter dem Gleitobjekt dieselben Zeilen nimmt, sodass ihre Köpfe auf gleicher Höhe bleiben, oder wenn die Zeilen diese Spalte bündig abschließen; eine Zeile, die den Kopf einer Spalte senken und sie dennoch kurz lassen würde, wird nicht eingefügt, und die Lücke geht an die lockeren Absätze weiter. `'always'` dehnt eine solche Spalte wie unter jedem Gleitobjekt, wie bis postext 1.27. Jeder andere Wert wird als `'flush'` gelesen. Seit postext 1.28; früher gespeicherte Dokumente behalten `'always'` (`pinLegacyWideFloatStretch`). |
| `looseParagraphs` | `boolean` | `true` | Letztes Mittel: Absätze einer kurzen Spalte eine Zeile lockerer neu umbrechen (je eine zusätzliche Zeile), innerhalb von `bodyText.maxWordSpacing`. |
| `maxLooseParagraphs` | `number` | `2` | Wie viele Absätze einer kurzen Spalte eine Zeile länger laufen dürfen, die längsten zuerst. |
| `trackParagraphs` | `boolean` | `true` | Kann der Wortabstand allein die Zeile nicht gewinnen, darf ein lockerer Absatz auch die kleinste positive Laufweite (Sperrung) nehmen, die es schafft. |
| `maxTracking` | `number` | `10` | Obergrenze dieser Laufweite, in Tausendstel eines Gevierts pro Zeichen (10 = 0,01 em). |
| `trailing` | `boolean` | `true` | Gleicht das Schlussband eines Kapitels und des Dokuments aus: Endet der Textfluss, bevor die Seite voll ist (an einem Kapitelauftakt, einem `:::part`, einem kapitelschließenden Kasten mit `placement: 'fixed'` oder am Ende des Dokuments), und sind seine Spalten ungleich, werden sie auf gleicher Höhe abgeschnitten – eine Bandgrenze von `ceil(Σ used / N / grid)` Zeilen, aufgelöst, nachdem die Hebel oben die früheren Seiten festgelegt haben –, sodass ein kurzes Literaturverzeichnis in jeder Spalte auf derselben Höhe endet, statt die erste Spalte zu füllen und die letzte halb leer zu lassen. Der Schnitt hält die Regeln ein, die ein ungeschnittenes Band einhält: Würde ein Block, der nicht über ihn hinweg geteilt werden kann (ein Absatzende, das die Mindestzeilen gegen Waisen und Witwen zusammenhalten, ein zusammenzuhaltender Kasten), über ihn hinauslaufen – und seine letzten Zeilen verlieren, da die Renderer eine Spalte auf ihren Rahmen zuschneiden – oder würde eine Überschrift eine Spalte schließen, während ihr Text die nächste eröffnet (mit `headings.keepWithNext`, dem Standard), wird der Schnitt eine Zeile tiefer gesetzt, bis zu dreimal, und sonst verworfen. Ein Block, der in den Zeilen, die der Schnitt unter einer eine Spalte anführenden Abbildung lässt, nicht beginnen kann (ein Absatz braucht dort sein Mindestmaß gegen Waisen), geht stattdessen in die nächste Spalte des Bands weiter, wie er es aus einer ungeschnittenen Spalte täte, und die Abbildung steht allein in ihrer Spalte. Spalten, deren Füße sich um eine Rasterzeile oder weniger unterscheiden, bleiben, wie sie sind: Ein Schlussband, dessen letzte Spalte eine Zeile kürzer endet, ist der übliche Abschluss, und ihn zu schneiden würde nur eine Zeile verschieben. Der Schnitt gilt dem Band, in dem er gemessen wurde, ebenso wie der Schnitt, den ein Kasten über die ganze Seitenbreite mitten auf der Seite verlangt: Bis postext 1.4 wurde der Schnitt, wenn der erste Text der Schlussseite zuerst einem Band ohne Platz dafür angeboten worden war (einer Seite, die ein Gleitobjekt ganz einnimmt, dem schmalen Band, das ein Kasten über die ganze Seitenbreite am Fuß der vorigen Seite lässt), an dieses Band vergeben, und die Schlussseite behielt jede Zeile in ihrer ersten Spalte. Spalten unterschiedlicher Breite (ein Anderthalb-Spalten-Layout mit Text in beiden) werden nach Fläche geschnitten, die Höhe jeder Spalte gewichtet mit ihrer Breite, da eine Zeile der schmalen Spalte weniger Text fasst. Nur wirksam, wenn `enabled` true ist. |
| `trailingStep` | `'lines' \| 'grid'` | `'lines'` | Die Einheit des Ausgleichsschnitts, den `trailing` nimmt (und des Schnitts, den `beforeSpan` hinter einem weiterrückenden Kasten nimmt). `'lines'`: Ein Band, dessen Text auf einem eigenen Zeilenabstand gesetzt ist (ein Register, ein Literaturverzeichnis, ein Container in kleiner Schrift), wird in ganzen Zeilen dieses Zeilenabstands geschnitten und neu versucht: der Höhe, die die meisten Zeilen des Bands teilen, Überschriften und Kästen beiseite. Seine Spalten enden dann innerhalb einer Zeile voneinander, wie ein Band aus Fließtext. Ein Band aus Fließtext und eines, das zwei Zeilenabstände zu gleichen Teilen mischt, wird wie bisher auf dem Grundlinienraster geschnitten. Ebenso ein Band, dessen Zeilen eine Höhe teilen und einen Zeilenbruchteil auseinanderstehen (Literaturangaben mit Abstand zwischen den Einträgen, Registergruppen auf einem von Hand gesetzten Rand): Vier von fünf Zeilen jeder Spalte müssen eine ganze Zahl von Zeilen voneinander entfernt sein. `'grid'`: Jeder Schnitt ist eine ganze Zahl von Zeilen des Grundlinienrasters, wie bis postext 1.27, wo ein Schnitt auf dem Raster eine Zeile mehr in eine Spalte eines Bands außerhalb des Rasters ließ und ein misslungener Schnitt um mehr als eine seiner Zeilen gesenkt wurde (Spalten bis zu drei Zeilen auseinander). Jeder andere Wert wird als `'lines'` gelesen. Seit postext 1.28; früher gespeicherte Dokumente behalten `'grid'` (`pinLegacyTrailingStep`). |
| `beforeSpan` | `boolean` | `true` | Gleicht das Band aus, das ein Block über die ganze Seitenbreite hinter sich lässt: Passt ein Kasten mit `span: 'page'` auch nach einem Ausgleichsschnitt nicht unter die aktuellen Spalten und muss er auf die nächste Seite rücken oder geteilt werden (`calloutStyles[].keepTogether: false`), werden die Spalten, die er unterbricht, auf gleicher Höhe abgeschnitten – mit derselben Grenze, die ein Schlussband erhält –, statt dass die erste die Seite füllt und die letzte kurz endet. Die Seite wird als ausdrücklicher Umbruch belassen, damit die Hebel oben ihre letzte Spalte nicht wieder bis zum Seitenfuß dehnen; der Kasten oder der Teil davon, der passt, steht dann unter den ausgeglichenen Spalten. Nur wirksam, wenn `enabled` true ist. |
| `closingBox` | `'first' \| 'last' \| 'off'` | `'first'` | Wann ein Kasten, der eine kurze Spalte schließt, den Raum unter seinem Fuß nimmt (Hebel 1, gespeichert als `trailingCallout`). `'first'`: vor jedem anderen Hebel, wie bis postext 1.4 – der Kasten nimmt die ganze Lücke, auch mehrere Zeilen, und die Überschriften darüber erhalten nichts. `'last'`: nach den Hebeln für Überschriften, Listenenden, abgesetzte Elemente und Gleitobjekte, die zuerst ganze Zeilen nehmen; der Kasten rückt mit dem Text darüber nach unten und nimmt dann nur, was sie übrig ließen, meist einen Zeilenbruchteil, sodass sein Fuß dennoch den letzten Rasterplatz trifft und er nah am Text bleibt, den er kommentiert. `'off'`: nie; der Kasten behält den Raum unter seinem Fuß, auch wenn die anderen Hebel ihn um ganze Zeilen nach unten bewegen können, wenn sie Abstand über ihm einfügen, und der Zeilenbruchteil unter ihm bleibt. Auf einer Schlussseite, wo der Kasten der einzige Hebel ist, der seinen Fuß mit der Spalte daneben fluchten lässt, lässt `'off'` ihn dort, wo der Textfluss ihn hingesetzt hat. Jeder andere Wert wird als `'first'` gelesen. Ein Kasten, der die einzige Textspalte seines Bands schließt (eine einspaltige Seite, die früh endet und deren nächster Block die nächste Seite eröffnet), wird nie bewegt: Es gibt keine Spalte daneben, mit der er fluchten müsste (seit postext 1.19). |
| `gridLines` | `'allow' \| 'off'` | `'allow'` | Auf einem Zeichenraster: ob die Hebel laufen dürfen, die ganze Rasterzeilen einfügen (über einer Überschrift, am Ende einer Liste, unter einem abgesetzten Element oder einem Kasten, unter einer die Spalte anführenden Abbildung). Sie halten jedes Zeichen in seiner Zelle; `'off'` passt zu einem Standard, der die Zeilen einer Seite zählt, und lässt die Spalte stattdessen kurz. Ohne Wirkung außerhalb des Rasters. Jeder andere Wert wird als `'allow'` gelesen. Seit postext 1.25. |

### Welcher Hebel gegriffen hat

Das Layout speichert jeden angewandten Hebel an dem Block, auf den er angewandt wurde: `block.balancing` im VDT, den `buildDocument` zurückgibt. Ein Korrekturbogen, ein Test oder ein Bericht kann so sagen, warum eine Spalte bündig endet – und welche Spalten kein Hebel schließen konnte. Blöcke, die der Ausgleich unberührt ließ, tragen kein `balancing`, und ein mit `enabled: false` gebautes Dokument hat keines.

Auf einem Zeichenraster sagt das Dokument, warum eine Spalte kurz enden darf: `doc.gridBalancing` ist `{ off: true }`, wenn der Ausgleich aus ist, weil die Seite auf einem Raster steht und die Konfiguration ihn nicht einschaltet, und `{ gridLines: 'off' }`, wenn er ohne die Hebel für ganze Zeilen läuft; eine noch kurze Spalte trägt `column.gridRefused`, die Hebel, die das Raster ihr vorenthielt (`'looseParagraph'`, wenn ein Absatz seine Zeile nur gewinnen könnte, indem er seine Zeichen aus ihren Zellen schiebt, die Hebel für ganze Zeilen unter `gridLines: 'off'`). Beide fehlen außerhalb des Rasters.

```ts
interface VDTBalancing {
  levers: BalanceLever[]; // usually one: a paragraph after a list can take the list-end line and run a line long too
  spaceAbove: number;     // px the spacing levers added above the block (0 when only looseParagraph or flexFigure fired)
  bodyGrowth?: number;    // flexFigure: px the picture grew, cropped within its safe area
  extraLines?: number;    // looseParagraph: lines the paragraph gained
  tracking?: number;      // looseParagraph: the tracking that gained them, in thousandths of an em (0 = word spacing alone)
}
type BalanceLever = 'trailingCallout' | 'flexFigure' | 'heading' | 'listEnd' | 'afterDisplay' | 'afterFloat' | 'looseParagraph';
```

| Hebel | Gespeichert an | Was er bewirkt hat |
| --- | --- | --- |
| `trailingCallout` | dem Rahmenblock des Kastens | Ein Kasten, der die Spalte schließt, ist um genau den Raum unter seinem Fuß nach unten gerückt (`spaceAbove`; ein Zeilenbruchteil ist zulässig). |
| `flexFigure` | dem Block (inline) oder Gleitobjekt des Bilds | Ein Bild mit Sicherheitsbereich, um `bodyGrowth` px höher gesetzt, in ganzen Rasterzeilen, innerhalb des Sicherheitsbereichs beschnitten. `bodySource` des Ressourcenblocks ist der gezeigte Teil und `bodyFlex.delta` dasselbe Wachstum. |
| `heading` | der Überschrift | Ganze Rasterzeilen über der Überschrift, bis `maxLinesPerHeading`. |
| `listEnd` | dem ersten Block nach der Liste | Eine Rasterzeile am Ende einer Liste, bis `maxLinesAfterList`. |
| `afterDisplay` | dem Block nach der Formel oder dem Kasten | Eine Rasterzeile unter einer abgesetzten Formel oder einem Kasten. |
| `afterFloat` | dem ersten Block der Spalte | Eine Rasterzeile zwischen einem Gleitobjektband, das die Spalte anführt, und ihrem Text, bis `maxLinesAfterFloat`. |
| `looseParagraph` | dem Absatz | Der Absatz wurde um `extraLines` länger neu umbrochen, mit der kleinsten Laufweite, die es schaffte (`tracking`; `block.letterSpacing` ist derselbe Wert in px). |

Die Ausgleichsschnitte werden an den Spalten gespeichert, die sie schneiden: `column.bandCapped` ist an jeder auf gleicher Höhe geschnittenen Spalte true (das Band, das ein Kasten über die ganze Seitenbreite hinter sich lässt, ein Schlussband), und `column.trailingCap` markiert zusätzlich das Schlussband eines Kapitels oder des Dokuments (`trailing`).

```ts
import { buildDocument } from 'postext';

const doc = buildDocument(content, config);
for (const page of doc.pages) {
  page.columns.forEach((column, i) => {
    const levers: string[] = column.blocks.flatMap((block) => block.balancing?.levers ?? []);
    if (column.trailingCap) levers.push('closing band cut level');
    else if (column.bandCapped) levers.push('band cut level');
    if (levers.length > 0) console.log(`page ${page.index + 1}, column ${i + 1}: ${levers.join(', ')}`);
  });
}
// page 3, column 1: heading, heading
// page 3, column 2: listEnd, looseParagraph
```
