Visuelles Formatierungsmodell

Im CSS beschreibt das visuelle Formatierungsmodell, wie Benutzeragenten den Dokumentbaum aufnehmen und für visuelle Medien verarbeiten und darstellen. Dies umfasst kontinuierliche Medien wie einen Computerbildschirm und Seitenmedien wie ein Buch oder ein Dokument, das durch Druckfunktionen des Browsers gedruckt wird. Die meisten Informationen gelten gleichermaßen für kontinuierliche und Seitenmedien.

Im visuellen Formatierungsmodell generiert jedes Element im Dokumentbaum null oder mehr Boxen gemäß dem Box-Modell. Die Anordnung dieser Boxen wird bestimmt durch:

  • Box-Abmessungen und -Typ.
  • Positionierungsschema (normaler Fluss, Float und absolute Positionierung).
  • Beziehungen zwischen Elementen im Dokumentbaum.
  • Externe Informationen (z.B. Viewport-Größe, intrinsische Abmessungen von Bildern, usw.).

Viele Informationen über das visuelle Formatierungsmodell sind in CSS2 definiert, jedoch haben verschiedene CSS-Layout-Module diese Informationen erweitert. Beim Lesen von Spezifikationen werden Sie oft Referenzen auf das in CSS2 definierte Modell finden, daher ist ein Verständnis des Modells und der in CSS2 verwendeten Begriffe wertvoll beim Lesen anderer Layout-Spezifikationen.

In diesem Dokument definieren wir das Modell und führen einige der zugehörigen Begriffe und Konzepte ein, mit Verlinkungen zu spezifischeren Seiten für weitere Details.

Die Rolle des Viewports

In kontinuierlichen Medien ist der Viewport der Anzeigebereich des Browserfensters. Benutzeragenten können das Layout der Seite ändern, wenn die Viewport-Größe sich ändert — zum Beispiel, wenn Sie Ihr Fenster in der Größe ändern oder die Ausrichtung eines mobilen Geräts ändern.

Wenn der Viewport kleiner als die Größe des Dokuments ist, muss der Benutzeragent eine Möglichkeit bieten, zu den Teilen des Dokuments zu scrollen, die nicht angezeigt werden. Am häufigsten sehen wir dies als Scrollen in der Block-Dimension — vertikal in einer horizontalen, von oben nach unten verlaufenden Sprache. Sie könnten jedoch auch etwas entwerfen, das Scrollen in der Inline-Dimension erfordert.

Box-Generierung

Box-Generierung ist der Teil des CSS-Visuellen Formatierungsmodells, der Boxen aus den Elementen des Dokuments erstellt. Generierte Boxen sind von unterschiedlichen Typen, die ihr visuelles Layout beeinflussen. Der Typ der generierten Box hängt vom Wert der CSS-Eigenschaft display ab.

In CSS2 ursprünglich definiert, wurde die display-Eigenschaft in den Modulen CSS display, CSS flexible box layout, CSS grid layout und CSS ruby layout erweitert. Zusätzlich wurde einige der Terminologien rund um die Darstellung seit CSS2 aktualisiert und klargestellt.

CSS nimmt Ihr Quelldokument und rendert es auf einer Leinwand. Dafür generiert es eine Zwischenstruktur, den Box-Baum, der die Formatierungsstruktur des gerenderten Dokuments darstellt. Jede Box im Box-Baum repräsentiert ihr entsprechendes Element (oder Pseudo-Element) im Raum und/oder in der Zeit auf der Leinwand, während jeder Textlauf im Box-Baum ebenfalls den Inhalt seiner entsprechenden Textknoten darstellt.

Dann generiert CSS für jedes Element null oder mehr Boxen, wie durch den display-Eigenschaftswert dieses Elements spezifiziert.

Hinweis: Boxen werden oft nach ihrem Display-Typ bezeichnet — z.B. eine Box, die von einem Element mit display: block generiert wird, wird als "Blockbox" oder einfach "Block" bezeichnet. Beachten Sie jedoch, dass Blockboxen, Blockebenenboxen und Blockcontainer alle etwas unterschiedlich sind; siehe den Abschnitt über Blockboxen weiter unten für mehr Details.

Die Hauptbox

Wenn ein Element eine oder mehrere Boxen generiert, ist eine davon die Hauptbox, die ihre Nachfahrenboxen und generierten Inhalte im Box-Baum enthält und auch die Box ist, die in irgendeinem Positionierungsschema beteiligt ist.

Einige Elemente können zusätzliche Boxen neben der Hauptbox generieren, z.B. generiert display: list-item mehr als eine Box (z.B. eine Haupt-Blockbox und eine Kind-Markierungsbox). Und einige Werte (wie none oder contents) bewirken, dass das Element und/oder seine Nachfahren überhaupt keine Boxen generieren.

Anonyme Boxen

Eine anonyme Box wird erstellt, wenn kein HTML-Element für die Box vorhanden ist. Diese Situation tritt auf, wenn Sie z.B. display: flex auf einem übergeordneten Element deklarieren, und direkt darin ein Textlauf enthalten ist, der nicht in ein anderes Element eingeschlossen ist. Um den Box-Baum zu korrigieren, wird eine anonyme Box um diesen Textlauf erstellt. Sie wird dann als Flex-Element agieren, kann jedoch nicht wie eine reguläre Box gezielt angesteuert oder gestylt werden, da es kein Ziel-Element gibt.

html
<div class="flex">
  I am wrapped in an anonymous box
  <p>I am in the paragraph</p>
  I am wrapped in an anonymous box.
</div>
css
body {
  font: 1.2em sans-serif;
  margin: 20px;
}

.flex {
  display: flex;
}

.flex > * {
  background-color: rebeccapurple;
  color: white;
}

Dasselbe passiert, wenn Sie Textläufe haben, die mit Blockelementen durchsetzt sind. Im nächsten Beispiel habe ich eine Zeichenkette in einem <div>; in der Mitte meiner Zeichenkette befindet sich ein <p>-Element, das einen Teil des Textes enthält.

html
<div class="example">
  I am wrapped in an anonymous box
  <p>I am in the paragraph</p>
  I am wrapped in an anonymous box.
</div>
css
body {
  font: 1.2em sans-serif;
  margin: 20px;
}

.example > * {
  background-color: rebeccapurple;
  color: white;
}

Die Zeichenkette wird im Box-Baum in drei Boxen aufgeteilt. Der Teil der Zeichenkette vor dem Absatz-Element wird in eine anonyme Box eingewickelt, dann haben wir das <p>, das eine Box generiert, und dann noch eine anonyme Box.

Etwas, das bei diesen anonymen Boxen zu beachten ist, ist, dass sie Stile von ihrem direkten übergeordneten Element erben, aber Sie können nicht ändern, wie sie aussehen, indem Sie die anonyme Box anvisieren. In meinen Beispielen verwende ich einen direkten Kind-Selektor, um die Kinder des Containers anzuvisieren. Dies ändert nicht die anonymen Boxen, da sie nicht im klassischen Sinne "Elemente" sind.

Inline-anonyme Boxen werden erstellt, wenn eine Zeichenkette durch ein Inline-Element unterbrochen wird, z.B. ein Satz, der einen Abschnitt umfasst, der mit <em></em> umschlossen ist. Dies teilt den Satz in drei Inline-Boxen — eine anonyme Inline-Box vor dem hervorgehobenen Abschnitt, den Abschnitt, der im <em>-Element umschlossen ist, dann eine abschließende anonyme Inline-Box. Wie bei den anonymen Blockboxen können diese anonymen Inline-Boxen nicht unabhängig vom <em> gestaltet werden; sie erben einfach die Stile ihrer Container.

Andere Formatierungskontexte erstellen ebenfalls anonyme Boxen. Grid layout verhält sich in gleicher Weise wie das Flexbox-Beispiel oben und verwandelt Textzeichenfolgen in ein Gitterelement mit einer anonymen Box. Mehrspaltiges Layout erstellt anonyme Spaltenboxen um die Spalten; diese können ebenfalls nicht gestylt oder anderweitig angesteuert werden. Tabellenlayout fügt anonyme Boxen hinzu, um eine ordnungsgemäße Tabellenstruktur zu erstellen — z.B. indem eine anonyme Tabellenzeile hinzugefügt wird — wenn keine Box mit display: table-row vorhanden war.

Linienboxen

Linienboxen sind die Boxen, die jede Textzeile umschließen. Sie können den Unterschied zwischen Linienboxen und ihrem umgebenden Block sehen, wenn Sie ein Item floaten und dann von einem Block, der eine Hintergrundfarbe hat, folgen lassen.

Im folgenden Beispiel werden die Linienboxen, die dem gefloateten <div> folgen, verkürzt, um den Float zu umschließen. Der Hintergrund der Box läuft hinter dem Float ab, da das gefloatete Element aus dem Fluss genommen wurde.

html
<div class="float"></div>
<p class="following">
  This text is following the float, the line boxes are shortened to make room
  for the float but the box of the element still takes position in normal flow.
</p>
css
body {
  font: 1.2em sans-serif;
  margin: 20px;
}

.float {
  float: left;
  width: 150px;
  height: 150px;
  background-color: rebeccapurple;
  margin: 20px;
}

.following {
  background-color: #ccc;
}

Positionierungsschemata und Elemente im Fluss und außerhalb des Flusses

In CSS kann eine Box nach drei Positionierungsschemata angeordnet werden — normaler Fluss, Floats oder absolute Positionierung.

Normaler Fluss

Im CSS umfasst der normale Fluss die Block-Level-Formatierung von Blockboxen, die Inline-Level-Formatierung von Inlineboxen und beinhaltet auch die relative und Sticky-Positionierung von Block-Level- und Inline-Level-Boxen.

Lesen Sie mehr über das Flow-Layout in CSS.

Floats

Im Float-Modell wird eine Box zunächst gemäß dem normalen Fluss angeordnet, dann aus dem Fluss herausgenommen und positioniert, typischerweise links oder rechts. Inhalte können an der Seite eines Floats entlang fließen.

Erfahren Sie mehr über Floats.

Absolute Positionierung

Im Modell der absoluten Positionierung (das auch fixed-Positionierung umfasst) wird eine Box vollständig aus dem normalen Fluss entfernt und relativ zu einem umgebenden Block positioniert (im Fall von fixierter Positionierung ist das der Viewport) oder relativ zu einem oder mehreren Ankerelementen in CSS-Ankerpositionierung.

Ein Element wird als außerhalb des Flusses bezeichnet, wenn es gefloatet, absolut positioniert oder das Wurzelelement ist. Ein Element wird als innerhalb des Flusses bezeichnet, wenn es nicht aus dem Fluss herausgenommen wurde.

Lesen Sie über das CSS Positioning Layout.

Formatierungskontexte und die Eigenschaft Display

Boxen können als ein äußerer Anzeigetyp beschrieben werden, der entweder block oder inline ist. Dieser äußere Anzeigetyp bezieht sich darauf, wie die Box zusammen mit anderen Elementen auf der Seite verhält.

Boxen haben auch einen inneren Anzeigetyp, der bestimmt, wie ihre Kinder sich verhalten. Für normales Block- und Inline-Layout oder normalen Fluss ist dieser Anzeigetyp flow. Dies bedeutet, dass die Kind-Elemente ebenfalls entweder block oder inline sein werden.

Der innere Anzeigetyp könnte jedoch auch etwas wie grid oder flex sein, wobei die direkten Kinder als Gitter- oder Flex-Elemente angezeigt werden. In einem solchen Fall wird das Element als Erzeuger eines Gitter- oder Flex-Formatierungskontexts beschrieben. In vielerlei Hinsicht ähnelt dies einem Blockformatierungskontext, jedoch verhalten sich die Kinder als Flex- oder Gitterelemente statt als Elemente im normalen Fluss.

Die Wechselwirkungen zwischen Block-Level- und Inline-Level-Boxen werden in der Eigenschaftsreferenz display beschrieben.

Zusätzlich erklären die Referenzen für spezifische Display-Werte, wie diese Formatierungskontexte in Bezug auf das Box-Layout funktionieren.

Unabhängige Formatierungskontexte

Elemente nehmen entweder am Formatierungskontext ihres umgebenden Blocks teil oder erstellen einen unabhängigen Formatierungskontext. Ein Gittercontainer erstellt zum Beispiel einen neuen Gitter-Formatierungskontext für seine Kinder.

Unabhängige Formatierungskontexte enthalten Floats, und Ränder kollabieren nicht über Formatierungskontext-Grenzen hinweg. Daher kann das Erstellen eines neuen Blockformatierungskontexts sicherstellen, dass Floats und Ränder innerhalb einer Box verbleiben. Um dies zu tun, fügen Sie display: flow-root zur Box hinzu, bei der Sie einen neuen Blockformatierungskontext erstellen möchten.

Das folgende Beispiel zeigt die Wirkung von display: flow-root. Die Box mit dem schwarzen Hintergrund scheint das gefloatete Element und den Text herum zu umschließen. Wenn Sie display: flow-root entfernen, wird das gefloatete Element aus der Unterseite der Box herausragen, da es nicht mehr enthalten ist.

html
<div class="container">
  <div class="item">Floated</div>
  <p>Text following the float.</p>
</div>
css
.container {
  display: flow-root;
}

.item {
  margin: 10px;
  float: left;
}

Blockboxen

In Spezifikationen werden Blockboxen, Block-Level-Boxen und Blockcontainer an bestimmten Stellen alle als Blockboxen bezeichnet. Diese Dinge sind etwas unterschiedlich und der Begriff Blockbox sollte nur verwendet werden, wenn keine Zweideutigkeit besteht.

Blockcontainer

Ein Blockcontainer enthält entweder nur Inline-Level-Boxen, die an einem Inline-Formatierungskontext teilnehmen, oder nur Block-Level-Boxen, die an einem Block-Formatierungskontext teilnehmen. Aus diesem Grund sehen wir das oben erklärte Verhalten, bei dem anonyme Boxen eingeführt werden, um sicherzustellen, dass alle Elemente an einem Block- oder Inline-Formatierungskontext teilnehmen können. Ein Element ist nur dann ein Blockcontainer, wenn es Block-Level- oder Inline-Level-Boxen enthält.

Inline-Level- und Block-Level-Boxen

Dies sind die Boxen, die sich im Blockcontainer befinden und an Inline- oder Block-Layout teilnehmen.

Blockboxen

Eine Blockbox ist eine Block-Level-Box, die auch ein Blockcontainer ist. Wie in CSS display beschrieben, kann eine Box eine Block-Level-Box sein, aber nicht auch ein Blockcontainer (sie könnte z.B. ein Flex- oder Gittercontainer sein).

Siehe auch