CSS/Tutorials/Boxmodell

Aus SELFHTML-Wiki
< CSS‎ | Tutorials
Wechseln zu: Navigation, Suche
CSS-icon.svg
Was vielen nicht bewusst ist: HTML ist von Haus aus responsiv - Block-Elemente wie Überschriften oder Absätze nehmen die gesamte Breite des Viewports ein und brechen überstehenden Text um, sodass er nach unten in einer neuen Zeile dargestellt wird.

Mit CSS können Sie jedoch Größenangaben und Abstände festlegen. Was auf unserem Symbolbild wie ein Unfall aussieht, zeigt eigentlich nur, wie viele Möglichkeiten CSS bietet.

  1. „klassisches“ Boxmodell
    • box-sizing
  2. Größenangaben
    • width
      • max-width + min-width
    • height
      • max-height + min-height
    • intrinsische Werte
      • max-content, min-content
      • fit-content()
      • minmax()
  3. übergroßer Inhalt
    • overflow
    • text-overflow
    • scroll
  4. Außenabstände (margin)
    • zusammenfallende Außenabstände
      (collapsing margins)
  5. Innenabstände (padding)
    • padding-bottom height fix
    • aspect-ratio
  6. Rahmen
    • border + border-radius
    • outline
    • box-shadow
  7. Logische Eigenschaften
    • block-size und inline-size
    • margin-block + margin-inline
    • padding-block + padding-inline
    • border-block + border-inline



Das „klassische“ Boxmodell[Bearbeiten]

Mit CSS können Sie Elementen (feste) Breiten, Höhen und Abstände geben und diese nebeneinander positionieren.

Die rechteckigen Blöcke, die im Elementbaum erzeugt und auf dem Bildschirm dargestellt werden, folgen einem Schema, dem „Box-Modell“. Es ist somit Grundlage jeden Layouts.

Jedes Block-Element wie Textabsätze (p), -Abschnitte (div, article, main, aside, …) und Überschriften (h1, h2, …) bildet eine rechteckige Box, die Sie frei formatieren können.

Im CSS-Einstieg haben wir Überschriften oft eine Text-und Hintergrundfarbe zugewiesen. Im folgenden Beispiel wollen wir die um Randlinien und Abstände erweitern:

Block-Elemente gestalten ansehen …
h1 {
  color: midnightblue;
  background-color: yellow;
  border: 1px solid;
  margin: 0;
  padding: 0;
}

.box {
  width: 200px;
  color: green;
  background-color: lightyellow;
  border:  2px solid red;
  border-radius: 0 1em 1em 1em;
  margin:  20px auto;
  padding: 2em;
}

Im Beispiel erhalten Überschrift h1 und Textabsatz p zusätzlich mit border noch eine Randlinie. Die Eigenschaft ist eine zusammenfassende „shorthand“-Eigenschaft der drei Werte für die Randstärke border-width, die Form border-style und den optionalen Wert für die Randfarbe border-color. Wird dort kein Wert zugewiesen, wird die Textfarbe des Elements verwendet.
Mit margin können Sie einen Abstand zum Elternelement und benachbarten Elementen festlegen. Die Überschrift „klebt“ durch margin: 0; am oberen Rand der Seite. Der Textabsatz erhält mit margin: 20px auto; einen Abstand von 20px nach oben (und unten), sowie mit auto einen gleichmäßig verteilten Abstand nach rechts und links. In Verbindung mit der Festlegung für die Breite width: 200px; wird der Textabsatz zentriert.
Die Überschrift stößt fast gegen die Randlinie; der Textabsatz hat mehr Platz. Das erreichen Sie durch eine Angabe eines Innenabstands padding (engl. für Polsterung)

Aufgabe:
  • Betrachten Sie das Beispiel im Frickl (einfacher Klick auf "Ausprobieren").
  • Verändern Sie im Frickl die Werte für Breite, Höhe, Randlinien und Abstände. Was beobachten Sie?

Alle diese Eigenschaften verwenden Längenangaben. Dabei können Sie absolute Werte in Pixel, aber auch relative Werte wie Prozentangaben und die Längeneinheit em, die die Größe der verwendeten Schriftart als Basisschriftgröße verwendet, verwenden.

padding oder margin?[Bearbeiten]

Es wird oft gefragt, welche der beiden Eigenschaften man verwenden soll – padding oder margin?

  • Wenn die Box eine eigene Hintergrundfarbe hat, soll der Rand um den Inhalt mit gefärbt sein (padding) oder nicht (margin)? Oder gar beides?
  • margins können überlappen (→ Collapsing margins). D.h. wenn ich zwei Boxen übereinander habe, und beide haben margin: 2em, dann ist der Abstand zwischen den Boxen 2em, nicht 4em.


Rechtecke nebeneinander[Bearbeiten]

Damit Text auf unserer Webseite gut lesbar ist, wollen wir ein Drei-Spaltenlayout entwerfen. Die Seite erhält eine feste Breite von 600px, die drei Spalten von je 200px.

Drei-Spaltenlayout ansehen …
.container {
  width: 600px; 
  height: 400px;
  border: 1px solid;
  padding: 0;

}

.spalte  {
  width:  200px;
  height: 200px;
  border:  1px solid red;
  margin:  5px;
  padding: 5px;
  display: inline-block;
}
Das Beispiel besteht aus dem Container-Element, das eine feste Breite von 600px und eine feste Höhe von 200px besitzt.

Als Spalten dienen drei section-Elemente, die eine feste Breite und Höhe von je 200px (ein Drittel von 600px) besitzen.
Damit die Divs nebeneinander platziert werden, erhalten sie ein display: inline-block;.

  • Betrachten Sie das Beispiel im Frickl als auch in einem neuen Tab. Was beobachten Sie?
  • Verändern Sie im Frickl die Werte für Breite, Höhe, Randlinien und Abstände. Was beobachten Sie?

Das Beispiel zeigt unerwünschtes Verhalten:

  • Warum werden die drei Boxen nicht nebeneinander dargestellt? Ein Blick in den Seiteninspektor (erreichbar mit F12) zeigt uns, dass die Spalten aus Boxen mit je 200px Breite, einer Randlinie von 1px und einem Innen- und Außenrand von je 5px, also ingesamt einer Gesamtbreite von 222px bestehen:

Box-Modell-Screenshot.png

Box-Modell-Screenshot-1.png

  • Die Boxen haben zu wenig Platz und ragen über die Elternelemente heraus: Obwohl das Container-Element eine vermeintlich ausreichende Höhe von 200px hat, ragen die beiden ersten Blöcke teilweise und der dritte Block ganz aus dem von uns falsch berechneten Rechteck heraus.
  • Im Frickl beträgt der Viewport des Beispiels weniger als die angegebenen 600px Breite, sodass ein horizontaler Scrollbalken erscheint.

Theorie: das klassische Box-Modell[Bearbeiten]

Wie im oben gezeigten Beispiel demonstriert, werden im Box-Modell alle Bestandteile einer Box addiert. Die Gesamtbreite errechnet sich aus:

margin-left + border-left + padding-left + width + padding-right + border-right + margin-right

Die Gesamthöhe einer Box wird ebenso errechnet.

Darstellung des CSS Box-Modells

In dieser interaktiven Demo können Sie die verschiedenen Möglichkeiten ausprobieren:

Fazit: Beim Layout müssen Sie zur angegebenen Breite alle Abstände und die Stärke der Randlinien dazurechnen, da dies die tatsächliche Breite des Block-Elements ergibt. Die mühselige Rechenart wurde früher weiter erschwert, da der Internet Explorer in den Versionen 5 und 5.5 einen als Box-Model-Bug bekannten Fehler hatte. Durch diesen Fehler wurden die Maße einer Box falsch berechnet: Die Maße für Rahmen und Innenabstände wurden nicht zu Breite und Höhe addiert, sondern davon abgezogen.

Dieser Fehler wurde in Version 6 behoben, jedoch im Quirks-Modus beibehalten. Das bedeutete, dass der Box-Modell-Fehler auch in neueren Internet Explorer Versionen auftrat, wenn nicht der standardkonforme Modus verwendet wurde.

Theorie 2: Box ist nicht gleich Box[Bearbeiten]

Eine Box hat zwei Darstellungsaspekte: die Außensicht und die Innensicht. Bei der Außensicht unterscheidet man zwischen Inline- und Block-Boxen, die Innensicht behandelt die diversen Layoutmodelle, die CSS anbietet. Jedes HTML Element ist entweder eine Inline- oder Block-Box. Die CSS Display Level 3 Spezifikation definiert auch eine Run-In Box, die aber (Stand 2022) nur der Internet Explorer kannte und auf die nicht eingegangen werden soll.

Das defaultmäßige Layoutmodell für fast alle Boxen ist flow, d.h. Inline-Boxen werden nebeneinander und Block-Boxen untereinander gesetzt. Ausnahme davon ist das table-Element mit seinen Kind-Elementen und das ruby-Element. Eine weitere Ausnahme entsteht, wenn für eine Box ein neuer Blockformatierungskontext gebildet wird, in diesem Fall lautet das Layout-Modell flow-root, was Auswirkungen auf das Verhalten von Rändern oder Floats hat.

Eine Box, deren Layoutmodell Flow (oder Flow-Root) ist, wird auch ein Block Container genannt. Diese Definition ist wichtig, denn einige CSS-Eigenschaften sind nur auf Block Container anwendbar. Andere Layoutmodelle sind Table, Flexbox, Grid und Ruby.

Sie können diese Darstellungsaspekte mit der CSS-Eigenschaft display festlegen. Die klassischen Werte inline oder block bezeichnen eine Inline- oder Block-Box mit Flow-Layout, ggf. auch flow-root Layout. Der Wert inline-block bezeichnet eine Inline-Box mit flow-root Layout, wodurch das Innenverhalten eines Blocks entsteht.

modernes WebDesign[Bearbeiten]

Um die Jahrtausendwende mussten WebDesigner mit Papier und Bleistift Breiten und Abstände zusammenrechnen, um ein pixelgenaues Layout für eine feste Größe von 640x480px (später auch 1024x768px) zu erstellen. Heute ist dies nicht mehr nötig:

Lösung 1: Das alternative Boxmodell[Bearbeiten]

Mit CSS3 wurde das starre Konzept des Boxmodells angepasst. Mithilfe der Eigenschaft box-sizing lässt sich spezifizieren, worauf sich die Angaben von width bzw. height beziehen sollen.


alternatives Boxmodel mit box-sizing: border-box; ansehen …
* {
  box-sizing: border-box;
}  
article {
  width: 40em; 
  border: 2px solid;
  display: table:
}

section, aside  {
  width: 33.333%;
  border:  1px solid red;
  margin:  0;
  padding: .5em;
  display: table-cell;
}

Durch box-sizing: border-box werden Innenabstand und Randlinie nun ohne weitere Berechnung von uns durch den Browser bei der Breitenberechnung berücksichtigt.
Bei der Verwendung von display:inline-block bilden sich kleine Abstände zwischen den Elementen. Durch die Verwendung von display:table für das Elternelement und display:table-cell für die Kindelemente können die drei Spalten direkt nebeneinander wie in einer Tabelle platziert werden.
Die Breite wird mit einem Prozentwert angegeben und muss bei einer eventuellen Änderung der Containerbreite nicht mehr angepasst werden.


Hinweis:
Durch die Verwendung von box-sizing: border-box lassen sich viele Schwierigkeiten beim Layouten umgehen. Dies gilt vor allem dann, wenn prozentuale Angaben für Abmessungen mit anderen Längenangaben kombiniert werden sollen.

Lösung 2: Der mathematische Weg[Bearbeiten]

Mit der calc()-Funktion können Sie eine mathematische Berechnung als Wert verwenden:

Drei-Spaltenlayout ansehen …
section, aside  {
  width: calc(33.3% - (2px + 10px + 10px));
  height: calc(200px - (2px + 10px ));
  border:  1px solid red;
  margin:  0 5px;
  padding: 5px;
  float: left;
}
Die Breitenangabe der Elemente mit der Klasse .spalte erhalten nun die Berechnung aus der Breite von einem Drittel als Prozentangabe und der Summe der Ränder: calc(33.3% - (2px + 10px + 10px))


Der Wert für height berechnet sich aus der absoluten Höhe, von der die Randstärke und der Innenabstand (der margin oben und unten beträgt 0) abgezogen werden.
Beachten Sie: Diese Lösung hat einige große Nachteile:
  • Bei jeder Änderung der Werte für Abstände und Randlinien müssen Sie die Formel anpassen!
  • Die Browser rechnen intern mit Integer-Werten anstatt „echten“ Pixeln (, die es im Gewirr zwischen physikalischen und logischen Pixeln gar nicht gibt). Deshalb kann es zu geringfügigen Rundungsfehlern kommen.
  • Die float-Eigenschaft ist dafür gedacht, Bilder oder andere Elemente innerhalb eines Textes umfließen zu lassen. Für mehrspaltige Layouts ist eine Umsetzung mit Flexbox oder dem Grid Layout Stand der Technik.
  • Die einzelnen Spalten haben eine feste Höhe. Wenn Sie, wie im zweiten section-Element, mehr Inhalt haben, ragt dieser über die Grenzen des Elements hinaus. („zerschossenes Layout“).
Hinweis:

Die hier vorgestellte Positionierung mit float ist heute verpönt, da sie viele Nachteile aufweist. Pixelgenaue Layouts sind immer nur für eine Auflösung optimiert und führen bei anderen Viewportgrößen zu Rändern oder einem „zerschossenen“ Layout.

Stand der Technik ist eine Umsetzung mit Flexbox oder dem Grid Layout:

Lösung 3: flexibles Layout[Bearbeiten]

Flexbox ist eine sehr moderne und einfache Möglichkeit, responsive und flexible Layouts zu erstellen, ohne feste Größenangaben und weitere CSS-Einstellungen wie position, float oder clear nutzen zu müssen. Dabei kann nicht nur die Größendarstellung, sondern auch die Reihenfolge der Elemente unabhängig vom HTML-Code durch CSS festgelegt werden.

flexibles Layout ansehen …
article {
  border: 1px solid;
  display: flex;  
}

section, aside  {
  border:  1px solid red;
  padding: 5px;
  flex: 1;
}
Dieses Beispiel besticht durch seine Einfachheit:
  • Das article-Element wird durch display: flex zum flexiblen Container.
  • Die einzelnen section-Elemente verteilen sich, da die Flex-basis mit flex: 1 gleich ist, gleichmäßig auf den verfügbaren Raum.

Fügen Sie im Frickl eine neue Spalte ein. Was können Sie beobachten?
Empfehlung:

Dieses Layout hat mehrere Vorteile:

  • Es passt sich flexibel an den vorhandenen Platz an.
  • Bei einer Änderung des Markups sind keine oder nur wenig Änderungen am CSS nötig.

Lösung 4: flexibel mit Grid Layout[Bearbeiten]

Mit dem Grid Layout Module ist es möglich, responsive zweidimensionale Layouts zu erstellen. Dabei wird ein Raster angelegt, in dem sich die Kindelemente ohne feste Größenangaben und weitere CSS-Einstellungen wie position, float oder clear bequem und flexibel positionieren (lassen).

flexibles Layout ansehen …
article {
  border: 1px solid;
  display: grid; 
  grid-template-columns: 1fr 1fr 1fr; 
  grid-gap: 1em;
}

section, aside  {
  border:  1px solid red;
  padding: 5px;
}
Dieses Beispiel besticht durch seine Einfachheit:
  • Das article-Element wird durch display: grid zum Grid-Container.
  • grid-template-columns: 1fr 1fr 1fr; legt drei gleichbreite Spalten an
  • grid-gap: 1em; lässt zwischen den Spalten (aber nicht am Außenrand) einen 1em breiten Rand
  • Die section-Elemente benötigen keine eigene Festlegungen!

Fügen Sie im Frickl eine neue Spalte ein. Was können Sie beobachten?
Empfehlung:

Dieses Layout hat mehrere Vorteile:

  • Es passt sich flexibel an den vorhandenen Platz an.
  • Bei einer Änderung des Markups sind keine oder nur wenig Änderungen am CSS nötig.


Fazit[Bearbeiten]

Empfehlung:
  • Verzichten Sie auf den Versuch ein pixelgenaues Layout erzeugen zu wollen.
    • Verzichten Sie auf Höhenangaben. Wenn der Inhalt größer wird, setzt er sich automatisch nach unten fort.
    • Verzichten Sie auf feste Breitenangaben. Verwenden Sie Eigenschaften wie min-width, um sicherzustellen, dass das Element breit genug für den Inhalt ist.
  • Verwenden Sie moderne, responsive Layout-Modelle wie Flexbox oder Grid Layout. Sie sind für alle Viewports geeignet und passen sich flexibel an den verfügbaren Platz an.

Im visuellen Anzeigemodell erfolgt die Darstellung von Elementen durch das Zeichnen von Rechtecken. Die Bestandteile dieser Rechtecke beschreibt das „Boxmodell“. Eine Box kann bestehen aus:

  • Dem Inhaltsbereich (client area), also der Fläche, die durch Texte und Bilder oder Eigenschaften wie width und height vorgegeben wird,
  • einem Innenabstand (padding),
  • einem Rahmen (border) und
  • einem Außenabstand (margin).

Bei Block-Elementen können Höhe und Breite beliebig festgelegt werden, bei Inlineelementen werden die Maße durch den Inhalt vorgegeben.

Innen- und Außenabstände sowie Rahmen können für jede der vier Seiten einer Box einzeln festgelegt werden.

Darstellung des CSS Box-Modells


Wird eine Box positioniert, beginnt die linke Außenkante bei left, die obere Außenkante bei top, die rechte Außenkante bei right und die untere Außenkante bei bottom. Da dies nur bei einer Schreibrichtung von links nach rechts wirklich stimmig ist, wurden die logischen Eigenschaften eingeführt, die im letzten Kapitel dieses Kurses vorgestellt werden.

Referenz-Box[Bearbeiten]

Die einzelnen Rechtecke werden von innen nach außen bezeichnet als

  • content-box: (Inhaltsbox) Bereich, der durch den Inhalt oder die Eigenschaften width und height festgelegt wurde.
  • padding-box: (Polsterungsbox) Bereich, der content-box und padding (Innenabstand) umfasst. Besitzt eine Seite keinen Innenabstand, so ist die Polsterungskante mit der Innenkante identisch.
  • border-box: (Rahmenbox) Box, die content-box, einen möglichen Innenabstand und die durch border festgelegten Rahmen umfasst. Besitzt eine Box keinen Rahmen, so ist die Rahmenbox mit der Polsterungsbox identisch.
  • margin-box: Box mitsamt durch margin festgelegten Außenabständen. Sind für eine Box keine Außenabstände definiert, so ist die Außenkante mit der Rahmenkante identisch.


Diese Bezeichnungen finden sich als Werte in einigen Eigenschaften wieder, etwa box-sizing, background-clip, background-origin oder mask.

Beachten Sie: Der Begriff „Box“ ist nicht mit dem Begriff „Element“ gleichzusetzen. Nicht jedes Element erzeugt eine Box, aber Boxen können auch erzeugt werden, wenn in einem Dokument kein Element als direktes Gegenstück existiert.

Was bei pixelgenauem Layout zu Rundungsfehlern, dem Zwang zu Browserweichen und zusätzlichem Wartungsaufwand führte, erwies sich im flexiblen Layout als nahezu unmöglich:

I would love a different box model! I find it bizarre that padding and border add the width of an object, and would love to be able to give something like a textarea 100% width and 3px padding without worrying what it’s going to do the layout. Perhaps something like padding-inside as a new selector?

In that vein I also wish I could specify a 100% width for an element, minus a set fixed width. Again, very useful when creating fluid designs with form elements!

Jon Hicks: CSS Wishlist: 21 Designer/Developers Sound Off[1]

Alternatives Box-Modell mit box-sizing[Bearbeiten]

Mit der box-sizing-Eigenschaft können Sie bestimmen, worauf sich Angaben zu den Abmessungen eines Elementes beziehen. Damit können Sie zwischen dem klassischen Boxmodell und dem intuitiveren des Quirksmodus umschalten.

Browserunterstützung
caniuse.com

Erlaubt sind dabei eine der folgenden Angaben.

  • content-box, Standardwert, Angabe gilt nur für den Inhalt
  • border-box, Angabe gilt für Inhalt, Innenabstand und Rahmen. Dies entspricht dem Quirksmodus des Internet Explorers.
content-box oder border-box? ansehen …
section {
  border: 1em solid green;
  padding: 1em;
  width: 20em;
}
#content-box {
  box-sizing: content-box;
}
#border-box {
  box-sizing: border-box;
}
<section id="content-box">
  ...
</section>
<section id="border-box">
  ...
</section>
Dieses Beispiel enthält zwei section-Elemente die jeweils einen Rahmen und einen Innenabstand der Breite 1em haben. Ebenso haben beide eine Breite von 20em zugewiesen bekommen.
Beim ersten section-Element wird eine Inhaltsbreite von 20em festgelegt, beim zweiten Element ergeben sich die 20em als Summe der Breiten von Inhalt, Innenabstand und Rahmen.

Praktischer Einsatz[Bearbeiten]

Empfehlung: Sie sollten im Sinne einer guten Wartbarkeit des CSS-Codes auf verschiedene Werte von box-sizing innerhalb eines Dokuments verzichten.

Die Eigenschaft box-sizing wird nicht automatisch vererbt. Deshalb schlug Chris Coyier vor, für die box-sizing Eigenschaft global den Wert inherit festzulegen.[2]

Miriam Suzanne widerspach diesem Ansatz auf der 2018er beyond tellerand Konferenz und empfahl, auf die Vererbung zu verzichten und einfach bei allen Elementen den Wert für box-sizing festzulegen:

There’s a reason that box model doesn’t inherit by default, and there’s no reason that it should inherit. We don’t inherit margins, we don’t inherit borders. Layouts should not be inherited; layouts don’t nest in that way. So I don’t recommend this solution.

Es gibt einen Grund, weshalb das Boxmodell nicht per Default vererbt wird, und es gibt keinen Grund, dass es vererbt werden sollte. Wir erben keine Margins, wir erben keine Borders. Layouts sollten nicht vererbt werden, Layouts schachteln sich nicht auf diese Art. Also, diese Lösung empfehle ich nicht.

Miriam Suzanne: Don’t use my grid system or any others (ab 8:15)[3]
Normalisierung von box-sizing
*, ::before, ::after { box-sizing: border-box; }
Die Eigenschaft box-sizing wird für alle Elemente auf border-box gestellt.

Siehe auch[Bearbeiten]

Weblinks[Bearbeiten]

Quellen

  1. Jon Hicks:CSS Wishlist: 21 Designer/Developers Sound Off
  2. Inheriting box-sizing Probably Slightly Better Best-Practice By Chris Coyier On July 15, 2014
    Vererbung von box-sizing
    html { box-sizing: border-box; } *, ::before, ::after { box-sizing: inherit; }
    Die Eigenschaft box-sizing wird nur für html eingestellt und alle Elemente erben den Wert ihres Elternelements. Hierdurch wird eine Änderung bei einem Element auf dessen Kindelemente weitervererbt. Bei *, ::before, ::after {box-sizing: border-box;} würden die Kindelemente einen anderen Ausgangswert nicht übernehmen.
  3. Miriam Suzanne:Don’t use my grid system or any others (ab 8:15)