mitmario.dev

box-sizing

CSS Im Browser 3 Min Lesezeit 3 BeispieleLektion 2 von 7

Du schreibst width: 300px an ein Element und misst nach: es ist 350 Pixel breit. Das ist kein Fehler des Browsers, sondern der eingebaute Standard, und er kostet Anfänger regelmäßig einen halben Nachmittag.

Woher die zusätzlichen Pixel kommen

Der Standard heißt content-box, und er nimmt width beim Wort: die Angabe meint den Inhalt, also den innersten der vier Ringe aus Lektion 4.1. Innenabstand und Rahmen liegen außen herum und kommen dazu.

Bei 300px Breite, 24px Innenabstand auf beiden Seiten und 1px Rahmen auf beiden Seiten ergibt das 300 plus 48 plus 2, also 350.

Die Rechnung geht nicht auf
/* Die Spalte ist 640px breit, jede Karte bekommt 300px.
   300 und 300 sind 600, es müsste also bequem passen. */
.spalte {
  width: 640px;
  background-color: #fef9c3;
}

/* content-box ist der Standard: width meint nur den Inhalt.
   Innenabstand und Rahmen kommen obendrauf, macht 350px. */
.karte {
  display: inline-block;
  vertical-align: top;
  width: 300px;
  padding: 24px;
  border: 1px solid #d4d4d8;
  background-color: #ffffff;
}

Die Spalte ist 640px breit und zwei Karten mit je 300px sollten locker hineinpassen. Tun sie nicht: zusammen sind sie 700px breit und die zweite rutscht in die nächste Zeile.

Das Tückische daran ist, dass die Rechnung im Kopf stimmt. Du hast dich nicht verrechnet, du hast nur eine andere Zahl gemeint als der Browser.

Nachmessen kannst du das direkt am Beispiel. Schalt das Fadenkreuz ein und fahr über eine der Karten: oben im Auskunftsstreifen steht 350 × 69, ein Stück weiter unten steht width = 300px. Dieselbe Karte, zwei verschiedene Zahlen. Die obere ist der Platz, den der Kasten wirklich einnimmt, die untere die Zahl, die du hingeschrieben hast. Was dazwischen liegt, steht ebenfalls im Streifen: padding = 24px auf beiden Seiten und border = 1px solid rgb(212, 212, 216), macht 48 plus 2.

border-box rechnet mit

Mit box-sizing: border-box bedeutet width die Gesamtbreite: Inhalt, Innenabstand und Rahmen zusammen. Der Inhalt schrumpft entsprechend, statt dass der Kasten wächst.

Mit border-box stimmt die Zahl
.spalte {
  width: 640px;
  background-color: #fef9c3;
}

/* Eine einzige Zeile Unterschied. Jetzt sind die 300px
   die Gesamtbreite, Innenabstand und Rahmen inklusive. */
.karte {
  box-sizing: border-box;
  display: inline-block;
  vertical-align: top;
  width: 300px;
  padding: 24px;
  border: 1px solid #d4d4d8;
  background-color: #ffffff;
}

Eine Zeile Unterschied, und die beiden Karten passen nebeneinander. Im Auskunftsstreifen sind die beiden Zahlen jetzt dieselbe: oben 300 × 69, unten width = 300px. Und in der Zeile box-sizing steht statt content-box jetzt border-box. Der Text hat innen etwas weniger Platz, weil die 48px Innenabstand jetzt von den 300 abgehen. Genau das wolltest du.

Der Außenabstand bleibt übrigens in beiden Modi außen vor. box-sizing betrifft nur die drei inneren Ringe, margin kommt immer obendrauf.

Der Reset

Weil border-box in praktisch jeder Situation das ist, was man meint, stellt man es nicht an einzelnen Elementen ein, sondern global.

Der Reset am Anfang der Datei
/* Diese vier Zeilen stehen am Anfang fast jedes Stylesheets.
   Die Pseudoelemente sind mit dabei, weil auch erzeugte
   Inhalte eigene Kästen sind (Lektion 2.6). */
*,
*::before,
*::after {
  box-sizing: border-box;
}

.kasten {
  width: 240px;
  padding: 16px;
  border: 4px solid #2563eb;
  background-color: #dbeafe;
}

Der Universalselektor kostet dich dabei nichts an Spezifität, denn * zählt null (Lektion 3.2). Du kannst die Einstellung also an jedem einzelnen Element wieder überschreiben, wenn du sie einmal nicht willst.

Die beiden Pseudoelemente stehen mit in der Liste, weil * sie nicht erfasst. Sie sind eigene Kästen mit eigenem Innenabstand und eigenem Rahmen, und sie sollen nach derselben Regel rechnen.

Warum drei Selektoren und nicht einfach eine Regel am html-Element: box-sizing vererbt sich nicht. Es gehört zu den Kasten-Eigenschaften aus Lektion 3.3, und die bleiben da, wo sie stehen. Der Universalselektor ist deshalb der einzige Weg, wirklich jedes Element zu erwischen.

Ab jetzt gehört dieser Block an den Anfang jeder Datei, die du schreibst. Er ist der Grund, warum in den folgenden Lektionen jede Breitenangabe einfach stimmt.

Warum das nicht von Anfang an so war

Die Frage kommt immer, also gleich die Antwort: content-box steht so in der ersten CSS-Spezifikation von 1996, und ändern lässt sich das nicht mehr. Jede Seite, die seither gebaut wurde, rechnet damit.

Kurios ist, dass die alten Internet-Explorer-Versionen es damals anders und aus heutiger Sicht besser gemacht haben. Sie rechneten wie border-box, und das galt jahrelang als der Fehler, den man umgehen musste. Als CSS3 die Eigenschaft einführte, bekam der bequemere Modus einen Namen und ist seitdem der Standard, den man sich selbst einschaltet.

Zum Mitnehmen

Mit border-box meint width endlich das, was du beim Hinschreiben gemeint hast. Deshalb steht der Reset am Anfang praktisch jedes Stylesheets der Welt.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

Was in dieser Lektion steckt

  • Artikel mit 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe im Editor, direkt im Browser geprüft

    Öffnet sich mit dem Basis Konto.