Breaking Boxes mit CSS-Fragmentierung
Veröffentlicht: 2022-03-10In diesem Artikel werde ich Ihnen die CSS-Fragmentierungsspezifikation vorstellen. Sie haben vielleicht noch nie davon gehört, aber wenn Sie jemals ein Druck-Stylesheet erstellt haben und kontrollieren wollten, wo der Inhalt zwischen Seiten oder einem mehrspaltigen Layout umbricht, und verhindern wollten, dass eine Abbildung zwischen Spalten umbricht, sind Sie darauf gestoßen.
Ich finde, dass ziemlich oft Probleme, die von Leuten mit Multicol gemeldet werden, wirklich Probleme mit der Browser-Unterstützung von Fragmentierung sind. Nach einem kurzen Überblick über die in dieser Spezifikation enthaltenen Eigenschaften werde ich den aktuellen Stand der Browserunterstützung und einige der Dinge erklären, die Sie tun können, damit sie in Ihren Multicol- und Druckprojekten so gut wie möglich funktioniert.
Was ist Fragmentierung?
Fragmentierung in CSS beschreibt den Prozess, bei dem Inhalte in verschiedene Boxen aufgeteilt werden. Derzeit haben wir zwei Stellen, an denen wir im Web auf Fragmentierung stoßen könnten: wenn wir ein Dokument drucken und wenn wir ein mehrspaltiges Layout verwenden. Diese beiden Dinge sind im Wesentlichen gleich. Wenn Sie eine Webseite drucken (oder als PDF speichern), wird der Inhalt in so viele Seiten fragmentiert, wie zum Drucken Ihres Inhalts erforderlich sind.
Wenn Sie multicol verwenden, wird der Inhalt in Spalten fragmentiert. Jede Spaltenbox ist wie eine Seite im Seitenkontext. Wenn Sie sich eine Reihe von Spalten ähnlich wie eine Reihe von Seiten vorstellen, kann es hilfreich sein, über Multicol nachzudenken und wie Fragmentierung darin funktioniert.
Wenn Sie einen Blick auf die CSS-Fragmentierungsspezifikation werfen, sehen Sie einen dritten fragmentierten Kontext, der erwähnt wird – dieser Kontext ist Regionen. Da es derzeit keine brauchbaren Implementierungen von Regionen gibt, werden wir uns in diesem Artikel nicht damit befassen, sondern stattdessen die beiden Kontexte betrachten, auf die Sie bei Ihrer Arbeit stoßen könnten.
Block- und Inline-Boxen
Ich werde Blockboxen in diesem Artikel häufig erwähnen. Jedes Element Ihrer Seite hat eine Box. Einige dieser Felder sind als Blöcke angelegt: Absätze, Listenelemente, Überschriften. Diese sollen an einem Blockformatierungskontext teilnehmen. Andere sind inline, wie die Wörter in einem Absatz, Spannen und Ankerelemente. Diese nehmen an einem Inline-Formatierungskontext teil. Einfach ausgedrückt, wenn ich mich auf eine Blockbox beziehe, spreche ich von Boxen um Dinge wie Absätze. Beim Umgang mit Fragmentierung ist es wichtig zu wissen, mit welcher Art von Box Sie es zu tun haben.
Weitere Informationen zum Block- und Inline-Layout finden Sie im MDN-Artikel „Block- und Inline-Layout im normalen Ablauf“. Es ist eines dieser Dinge, die wir wahrscheinlich alle auf einer gewissen Ebene verstehen, aber der Terminologie von früher vielleicht nicht begegnet ist.
Pausen kontrollieren
Unabhängig davon, ob Sie ein Druck-Stylesheet erstellen, einen bestimmten Druck-Benutzeragenten verwenden, um ein PDF zu erstellen, oder Multicol verwenden, werden Sie manchmal auf Probleme stoßen, die so aussehen.
Im folgenden Multicol-Beispiel habe ich einige Inhalte, die ich als drei Spalten anzeige. In der Mitte des Inhalts befindet sich ein gerahmter Bereich, der über zwei Spalten aufgeteilt wird. Ich möchte dieses Verhalten nicht – ich möchte, dass die Box zusammen bleibt.
Um dies zu beheben, füge ich der Box die Eigenschaft break-inside: avoid
Avoid hinzu. Die break-inside
Eigenschaft steuert Umbrüche innerhalb von Elementen, wenn sie sich in einem fragmentierten Kontext befinden. In einem Browser, der diese Eigenschaft unterstützt, bleibt das Kästchen nun in einer der Spalten. Die Spalten werden weniger gut ausbalanciert aussehen, aber das ist im Allgemeinen besser, als wenn die Boxout auf Spalten aufgeteilt wird.
Die break-inside
Eigenschaft ist eine der in der Fragmentierungsspezifikation aufgeführten Eigenschaften. Die vollständige Liste der Eigenschaften lautet wie folgt:
-
break-before
-
break-after
-
break-inside
-
orphans
-
widows
-
box-decoration-break
Lassen Sie uns einen Blick darauf werfen, wie diese funktionieren sollen, bevor wir zu dem übergehen, was tatsächlich in Browsern passiert.
Die break-before
und break-after
Eigenschaften
Es gibt zwei Eigenschaften, die Umbrüche zwischen Boxen auf Blockebene steuern: break-before
und break-after
. Wenn Sie ein h2
gefolgt von zwei Absätzen <p>
haben, haben Sie drei Blockboxen und Sie würden diese Eigenschaften verwenden, um die Umbrüche zwischen der Überschrift und dem ersten Absatz oder zwischen den beiden Absätzen zu steuern.
Die Eigenschaften werden für Selektoren verwendet, die auf das Element abzielen, vor oder nach dem Sie umbrechen möchten.
Sie möchten beispielsweise, dass Ihr Druck-Stylesheet jedes Mal auf einer neuen Seite umbricht, wenn eine Überschrift der Ebene 2 vorhanden ist. In diesem Fall würden Sie break-before: page
auf dem h2
-Element verwenden. Dies kontrolliert die Fragmentierung und sorgt dafür, dass vor der Box des h2
-Elements immer eine Pause ist.
h2 { break-before: page; }
Eine weitere häufige Anforderung besteht darin, zu verhindern, dass Überschriften als letztes Element auf einer Seite oder Spalte landen. In diesem Fall könnten Sie break-after
mit dem Wert avoid
verwenden. Damit soll ein Umbruch direkt nach der Box des Elements verhindert werden:
h1, h2, h3, h4 { break-after: avoid; }
Fragmente innerhalb von Fragmenten
Es ist möglich, dass Sie ein Element haben, das fragmentiert in einem anderen verschachtelt ist. Zum Beispiel ein Multicol in etwas zu haben, das ausgelagert ist. In diesem Fall möchten Sie möglicherweise Umbrüche für Seiten, aber nicht für Spalten oder umgekehrt steuern. Aus diesem Grund haben wir Werte wie page
, die immer einen Umbruch vor oder nach dem Element erzwingen würden, aber nur, wenn das Fragment eine Seite ist. Oder avoid-page
, die einen Umbruch vor oder nach dem Element nur für Seitenkontexte vermeiden würde.
Gleiches gilt für Spalten. Wenn Sie die column
verwenden, würde dies immer einen Umbruch vor oder nach diesem Element erzwingen, aber nur für mehrspaltige Kontexte. Der Wert avoid-column
würde einen Break in Multicol-Kontexten verhindern.
Es gibt einen always
-Wert in der Level-4-Spezifikation, der angibt, dass Sie alles durchbrechen möchten – Seite oder Spalte. Da es jedoch kürzlich zur Spezifikation hinzugefügt wurde, ist es für uns derzeit nicht nützlich.
Zusätzliche Werte für ausgelagerte Medien
Wenn Sie ein Buch oder eine Zeitschrift erstellen, haben Sie linke und rechte Seiten. Möglicherweise möchten Sie das Umbrechen steuern, um etwas auf die linke oder rechte Seite einer Doppelseite zu zwingen. Daher würde die Verwendung des Folgenden einen oder zwei Seitenumbrüche vor dem h2
einfügen, um sicherzustellen, dass es als richtige Seite formatiert wurde.
h2 { break-before: right; }
Es gibt auch Recto- und Verso-Werte, die sich auf die Seitenfolge beziehen, da Bücher, die in einer vertikalen oder von rechts nach links geschriebenen Sprache geschrieben sind, eine andere Seitenfolge haben als Bücher, die auf Englisch geschrieben sind. Ich werde diese Werte in diesem Artikel nicht weiter behandeln, da es mir diesmal hauptsächlich darum geht, was vom Browser aus möglich ist.
break-inside
Wir haben bereits ein Beispiel für die break-inside
Eigenschaft gesehen. Diese Eigenschaft steuert den Umbruch innerhalb von Blockboxen, zB innerhalb eines Absatzes, einer Überschrift oder eines div.
Dinge, die Sie möglicherweise nicht unterbrechen möchten, können wie oben beschrieben eine Boxout enthalten: Abbildungen, bei denen die Beschriftung nicht vom Bild getrennt werden soll, Tabellen, Listen und so weiter. break-inside: avoid
Sie alle Container, die Sie in keinem Fragmentierungskontext unterbrechen möchten. Wenn Sie nur Umbrüche zwischen Spalten vermeiden möchten, verwenden Sie break-inside: avoid-column
und zwischen Seiten break-inside: avoid-page
.
Die Eigenschaften der orphans
und widows
Die Eigenschaften orphans
und widows
befassen sich damit, wie viele Zeilen vor oder nach einem Umbruch (entweder verursacht durch eine Spalte oder eine neue Seite) übrig bleiben sollen. Wenn ich beispielsweise vermeiden möchte, dass am Ende einer Spalte eine einzelne Zeile übrig bleibt, würde ich die Eigenschaft orphans
verwenden, da in der Typografie ein Waisenkind die erste Zeile eines Absatzes ist, die allein am Ende einer Seite mit erscheint der Rest des Absatzes auf eine andere Seite umgebrochen. Die Eigenschaft sollte demselben fragmentierenden Element hinzugefügt werden (in unserem Fall dem Multicol-Container).
.container { column-count: 3; orphans: 2; }
Um zu steuern, wie viele Zeilen nach einem Umbruch am Anfang einer Spalte oder Seite stehen sollen, verwenden widows
:
.container { column-count: 3; widows: 2; }
Diese Eigenschaften behandeln Umbrüche zwischen Inline-Boxen, wie z. B. Wortzeilen innerhalb eines Absatzes. Daher helfen sie nicht in der Situation, in der eine Überschrift oder ein anderes Blockelement allein am Ende einer Spalte oder Seite steht, dafür benötigen Sie die oben besprochenen Break-Eigenschaften.
Box-Dekoration
Eine letzte Eigenschaft, die von Interesse sein könnte, ist die box-decoration-break
Eigenschaft. Dies steuert die Situation, in der Sie ein Feld mit einem unterbrochenen Rahmen zwischen zwei Spaltenfeldern oder Seiten haben. Möchten Sie, dass der Rand im Wesentlichen in zwei Hälften geschnitten wird? Oder möchten Sie, dass jede der beiden Hälften der Schachtel vollständig in eine Bordüre eingewickelt wird?
Das erste Szenario ist die Standardeinstellung und ist so, als ob Sie die box-decoration-break
Eigenschaft so slice
, dass sie auf der Box aufteilt.
.box { box-decoration-break: slice; }
Um das zweite Verhalten zu erhalten, setzen Sie box-decoration-break
auf clone.
.box { box-decoration-break: clone; }
Browserunterstützung für Fragmentierung
Jetzt kommen wir zu dem Grund, warum ich oben nicht eine Reihe von CodePen-Beispielen habe, um Ihnen das alles zu demonstrieren, und dem Hauptgrund, warum ich diesen Artikel schreibe. Die Browserunterstützung für diese Eigenschaften ist nicht großartig.
Wenn Sie in Paged Media mit einem bestimmten Benutzeragenten wie Prince arbeiten, können Sie sich über eine wirklich gute Unterstützung für die Fragmentierung freuen und werden diese Eigenschaften wahrscheinlich sehr nützlich finden. Wenn Sie mit einem Webbrowser arbeiten, entweder in Multicol, Druck-Stylesheets erstellen oder etwas wie Headless Chrome zum Generieren von PDFs verwenden, ist die Unterstützung etwas lückenhaft. Sie werden feststellen, dass der Browser mit der besten Unterstützung Edge ist – bis er sowieso zu Chromium wechselt!
Can I Use ist nicht besonders hilfreich bei der Erläuterung der Unterstützung, da die Fragmentierungseigenschaften mit Multicol gemischt werden und dann einige separate Daten für Legacy-Eigenschaften vorhanden sind. Als Teil der Arbeit, die ich für MDN geleistet habe, um die Eigenschaften und ihre Unterstützung zu dokumentieren, habe ich begonnen, die tatsächliche Browserunterstützung zu testen. Was folgt, sind einige Ratschläge, die auf diesen Tests basieren.
Legacy- und Anbieter-Präfix-Eigenschaften
Ohne Geschichtsunterricht komme ich nicht weiter. Wenn Sie feststellen, dass Sie wirklich Unterstützung für die Fragmentierung benötigen, finden Sie möglicherweise eine gewisse Erleichterung in den Legacy-Eigenschaften, die ursprünglich Teil von CSS2 waren (oder in einigen vorhandenen Eigenschaften mit Präfix).
In CSS2 gab es Eigenschaften, um den Seitenumbruch zu steuern. Multicol existierte zu diesem Zeitpunkt noch nicht, daher war der einzige fragmentierte Kontext ein ausgelagerter. Dies bedeutete, dass drei spezifische Seitenumbrucheigenschaften eingeführt wurden:
-
page-break-before
-
page-break-after
-
page-break-inside
Diese funktionieren auf ähnliche Weise wie die allgemeineren Eigenschaften ohne das page-
und steuern Umbrüche vor, nach und innerhalb von Boxen. Bei Druck-Stylesheets werden Sie feststellen, dass einige ältere Browser, die die neuen break-
Eigenschaften nicht unterstützen, diese Seitenpräfix-Eigenschaften unterstützen. Die Eigenschaften werden als Aliase für die neuen Eigenschaften behandelt.
In einem Arbeitsentwurf der Multicol-Spezifikation aus dem Jahr 2005 sind Einzelheiten zu den Breaking-Eigenschaften für Multicol enthalten – wobei Eigenschaften mit dem Präfix column-
(dh column-break-before
, column-break-after
und column-break-inside
) verwendet werden. Bis 2009 waren diese verschwunden, und in der Multicol-Spezifikation befand sich ein Entwurf für nicht präfixierte Break-Eigenschaften, der schließlich seinen Weg in die CSS-Fragmentierungsspezifikation fand.
Einige spaltenspezifische Eigenschaften mit Präfix des Anbieters wurden jedoch basierend auf diesen Eigenschaften implementiert. Diese sind:
-
-webkit-column-break-before
-
-webkit-column-break-after
-
-webkit-column-break-inside
Unterstützung für Fragmentierung in Multicol
Das Folgende basiert auf dem Testen dieser Features in Multicol-Kontexten. Ich habe versucht zu erklären, was möglich ist, aber werfen Sie einen Blick auf die CodePens in den Ihnen zur Verfügung stehenden Browsern.
Bunt und break-inside
Die Unterstützung in Multicol ist für die break-inside
Eigenschaft am besten. Aktuelle Versionen von Chrome, Firefox, Edge und Safari unterstützen alle break-inside: avoid
Sie . Sie sollten also feststellen, dass Sie verhindern können, dass Boxen zwischen Spalten umbrechen, wenn Sie multicol verwenden.
Mehrere Browser, mit Ausnahme von Firefox, unterstützen die -webkit-column-break-inside
, diese kann mit einem Wert von avoid
verwendet werden und kann verhindern, dass Boxen zwischen Spalten umbrechen, die break-inside
nicht unterstützen.
Firefox unterstützt page-break-inside: avoid
Sie in Multicol. Daher verhindert die Verwendung dieser Eigenschaft Umbrüche innerhalb von Kästchen in Firefox-Browsern vor Firefox 65.
Das bedeutet, wenn Sie Umbrüche zwischen Kästchen in Multicol verhindern möchten, deckt die Verwendung des folgenden CSS so viele Browser wie möglich ab und geht so weit wie möglich zurück.
.box { -webkit-column-break-inside: avoid; page-break-inside: avoid; break-inside: avoid; }
Was den column
betrifft, funktioniert die ausdrückliche Angabe, dass Sie nur Umbrüche zwischen Spalten und nicht zwischen Seiten vermeiden möchten, in allen Browsern außer Firefox.
Der folgende CodePen fasst einige dieser Tests in Multicol zusammen, damit Sie sie selbst ausprobieren können.
Bunt und break-before
Um Umbrüche vor einem Element zu verhindern, sollten Sie break-before: avoid
oder break-before: avoid-column
verwenden können. Die Eigenschaft Avoid hat keine Browserunterstützung.
Edge unterstützt break-before: column
, um immer einen Break vor der Box des Elements zu erzwingen.
Safari, Chrome und Edge unterstützen auch -webkit-column-break-before: always
, was einen Umbruch vor dem Kästchen des Elements erzwingt. Wenn Sie also einen Umbruch vor der Box eines Elements erzwingen möchten, sollten Sie Folgendes verwenden:
.box { -webkit-column-break-before: always; break-before: column; }
Ein Break vor dem Strafraum zu verhindern, ist derzeit eine unmögliche Aufgabe. Sie können unten mit einigen Beispielen dieser Eigenschaften herumspielen:
Multicol und break-after
Um Unterbrechungen nach einem Element zu vermeiden, damit es nicht das letzte Element am Ende einer Spalte wird, sollten Sie in der Lage sein, break-after: avoid
und break-after: avoid-column
zu verwenden. Der einzige Browser, der diese unterstützt, ist Edge.
Edge unterstützt auch das Erzwingen von Umbrüchen nach einem Element durch Verwendung von break-after: column
, Chrome unterstützt break-after: column
und auch -webkit-column-break-after: always
.
Firefox unterstützt kein break-after
oder irgendeine der vorangestellten Eigenschaften, um Breaks nach einem Kästchen zu erzwingen oder zuzulassen.
Daher sind Pausen nach einer Box anders als bei Edge nicht wirklich zu vermeiden. Wenn Sie sie erzwingen möchten, erhalten Sie in einigen Browsern Ergebnisse, indem Sie das folgende CSS verwenden:
.box { -webkit-break-after: always; break-after: column; }
Unterstützung beim Drucken aus dem Browser
Ob Sie direkt aus Ihrem Desktop-Browser drucken oder PDF-Dateien mit Headless Chrome oder einer anderen auf Browsertechnologie basierenden Lösung generieren, spielt keine Rolle. Sie sind auf die Browserunterstützung für die Fragmentierungseigenschaften angewiesen.
Wenn Sie ein Druck-Stylesheet erstellen, finden Sie eine ähnliche Unterstützung für die Break-Eigenschaften wie für multicol; Um jedoch ältere Browser zu unterstützen, sollten Sie die Eigenschaften verdoppeln, um die Eigenschaften mit dem page-
zu verwenden.
Stylesheets drucken Und break-inside
In modernen Browsern kann die Eigenschaft break-inside
verwendet werden, um Umbrüche innerhalb von Boxen zu verhindern, fügen Sie die Eigenschaft page-break-inside
hinzu, um Unterstützung für ältere Browser hinzuzufügen.
.box { page-break-inside: avoid; break-inside: avoid; }
Drucken Sie Stylesheets und break-before
ab
Um Umbrüche vor einer Box zu erzwingen, verwenden Sie break-before:page
zusammen mit page-break-before: always
.
.box { page-break-before: always; break-before: page; }
Um Umbrüche vor einer Box zu vermeiden, verwenden Sie break-before: avoid-page
zusammen mit page-break-before: avoid
.
.box { page-break-before: avoid; break-before: avoid-page; }
Die page
und avoid-page
Werte. Die Mehrheit der modernen Browser unterstützt dies.
Drucken Sie Stylesheets und break-before
ab
Um Umbrüche nach einer Box zu erzwingen, verwenden break-after: page
zusammen mit page-break-after: always
.
.box { page-break-after: always; break-after: page; }
Um Umbrüche nach einer Box zu verhindern, verwenden Sie break-after: avoid-page
zusammen mit page-break-after: avoid
.
.box { page-break-after: avoid; break-after: avoid-page; }
Witwen und Waisen
Die Eigenschaften der widows
und orphans
genießen eine gute Cross-Browser-Unterstützung – der einzige Browser ohne Implementierung ist Firefox. Ich würde vorschlagen, diese beim Erstellen eines mehrfarbigen Layouts oder Druck-Stylesheets zu verwenden. Wenn sie aus irgendeinem Grund nicht funktionieren, werden Sie Witwen und Waisen bekommen, was nicht ideal ist, aber auch keine Katastrophe. Wenn sie funktionieren, wird Ihre Typografie umso besser aussehen.
Box-Dekoration-Pause
Die letzte Eigenschaft von box-decoration-break
unterstützt Multicol und Print in Firefox. Safari, Chrome und andere Chromium-basierte Browser unterstützen -webkit-box-decoration-break
, aber nur für Inline-Elemente. So können Sie zum Beispiel Rahmen um Zeilen eines Satzes klonen; sie haben keine Unterstützung in dem Kontext, den wir betrachten.
Im CodePen unten können Sie sehen, dass das Testen auf -webkit-box-decoration-break: clone
with Feature Queries true zurückgibt; Die Eigenschaft hat jedoch keine Auswirkung auf den Rand der Box im multicol-Kontext.
Fragmentierung verwenden
Wie Sie sehen können, ist der aktuelle Stand der Fragmentierung in Browsern etwas fragmentiert! Das heißt, es gibt eine vernünftige Menge, die Sie erreichen können, und wo es fehlschlägt, ist das Ergebnis tendenziell suboptimal, aber keine Katastrophe. Es lohnt sich also, es zu versuchen.
Es ist erwähnenswert, dass ein zu schwerer Umgang mit diesen Eigenschaften zu etwas anderem führen kann, als Sie es sich erhofft haben. Wenn Sie im Web arbeiten, anstatt nach jedem Absatz Spaltenumbrüche zu drucken und zu erzwingen, dann am Ende mehr Absätze als Platz für Spalten haben, wird Multicol am Ende in Inline-Richtung überlaufen. Es werden keine Spalten mehr vorhanden sein, um Ihre zusätzlichen Absätze zu platzieren. Daher müssen Sie auch dort, wo es Unterstützung gibt, sorgfältig testen und sich daran erinnern, dass weniger in vielen Fällen mehr ist.
Mehr Ressourcen
Um mehr über die Eigenschaften zu erfahren, gehen Sie zu MDN, ich habe die Seiten dort kürzlich aktualisiert und versuche auch, die Browserkompatibilitätsdaten auf dem neuesten Stand zu halten. Die Hauptseite für CSS-Fragmentierung verlinkt auf die einzelnen Eigenschaftsseiten, die weitere Beispiele, Browserkompatibilitätsdaten und andere Informationen zur Verwendung dieser Eigenschaften enthalten.