CSS Calc - Breiten- und Höhenangaben durch Berechnung festlegen

In CSS können den Elementen Breiten- und Höhenangaben mit width und height angegeben werden. Als Einheiten hat man verschiedene Möglichkeiten, z.B. px, em oder % (Prozent). Beim Standard Box-Modell bezieht sich die Angabe auf den Inhaltsbereich. Etwaige Innenabstände (padding) oder Rahmen (border) werden zur Box hinzu addiert. Außerdem nimmt der Außenabstand (margin) den Platz im äußeren Bereich ein. Das kann in manchen Fällen zu Problemen führen. Ein Beispiel hierfür ist eine Raster-Navigation, die eine gute Lösung für eine Navigation auf Websites mit responsive Design sein können.

Angenommen, man möchte den Boxen mit den Hyperlinks eine Breite von 50% zuweisen, damit immer zwei Navigationspunkte nebeneinander angeordnet werden. Da zwei Navigationspunkte 100% des Anzeigebereichs füllen, hat man in jeder Zeile zwei Elemente und man erhält ein Raster-Menü. Wenn man den einzelnen Boxen nun einen Rahmen zuweist, dann haben sie eine Bereite von 50% + Rahmenbreite, da der Rahmen zur Box hinzu addiert wird. Die Folge ist, dass zwei Navigationspunkte nicht mehr nebeneinander angeordnet werden können, da sie zusammen mit der Rahmenbreite 100% überschreiten, selbst wenn der Rahmen nur 1px breit ist. Knapp überschritten ist trotzdem überschritten.

Raster-Navigation mit 50% Breite

Lösung ab CSS3 mit calc()

Das Grundproblem an dieser Stelle ist, dass man die Breite der Box prozentual angibt und die Rahmenbreite rechtes und links in Pixel hinzu addiert wird. Es müsste daher eine Möglichkeit geben, für die Box eine Breite in der Form "<x>% - <x>px" anzugeben. Ab CSS3 ist das mit calc() möglich. Innerhalb der runden Klammern kann ein Ausdruck für die Berechnung eingegeben werden. Nachfolgend ist die Syntax anhand eines Beispiels abgebildet.

Syntax CSS für calc

Als mathematische Operatoren verwendet man dabei folgende Zeichen:

  • Für Addition: +
  • Für Subtraktion: -
  • Für Division: /
  • Für Multiplikation: *

Die beiden Operatoren für Division und Multiplikation (/ und *) müssen nicht zwischen Leerzeichen platziert werden. Die beiden Operatoren + und - ist benötigen jedoch links und rechts ein Leerzeichen. Die folgenden Beispiele wären gültig.

.selektor1 {
width: calc(50% - 4px);
}

.selektor2 {
width: calc(50% + 4px);
}

.selektor3 {
width: calc(50%*2);
}

.selektor4 {
width: calc(50%/2);
}

Fallback für ältere Browser

Einige ältere Browser benötigen ein Browser-Präfix, um eine Berechnung mit calc() berücksichtigen zu können. Vor allem ältere Browser kennen calc() überhaupt nicht. Für diese wird ein Fallback benötigt. Ein Beispielcode.

.selektor {
/* Fallback für nicht unterstützende Browser */
width: 48%;

/* Für Browser, die ein Präfix benötigen */
width: -webkit-calc(50% - 4px);
width: -moz-calc(50% - 4px);

/* Reguläre Angabe */
width: calc(50% - 4px);
}

Alternatives Box-Modell mit box-sizing

Ab CSS3 ist es ebenfalls möglich, mit box-sizing auf ein alternatives Box-Modell umzuschalten. Hierbei werden keine Berechnungen durchgeführt. Es wird lediglich angegeben, dass die Breite für einen Bereich inklusive padding und border gilt.

Lösungsmöglichkeit vor CSS3

Vor CSS3 hatte man kaum im Grunde kaum Möglichkeiten, prozentuale Einheiten mit anderen zu kombinieren. Man könnte annehmen, dass die Lösung darin bestünde, die Maße für den Rahmen und die Box nur in Prozent anzugeben, z.B. 48% für die Box und 1% für den Rahmen, sodass man insgesamt eine Breite von 50% erhält. Das Problem hierbei ist, dass eine prozentuale Angabe für den Rahmen nicht möglich ist.

Eine funktionierende Variante war, den Innenabstand padding für den Rahmen zu "missbrauchen". Hierbei wird ein äußerer Rahmen mit einer Breite von 50% festgelegt. Innerhalb der Box wird eine weitere Box mit einer prozentualen Angabe für den padding und einer Hintergrundfarbe festgelegt, die sozusagen als Rahmenfarbe dient. Innerhalb der Box wird wiederum die eigentliche Box mit einer Breite von 100% platziert, die den eigentlichen Inhalt enthält. Nachfolgend sind Beispielcodes, um zwei Elemente nebeneinander zu platzieren und mit padding die Hintergrundfarbe einer Box als Rahmen zu verwenden.

.aussen {
width: 50%;
float: left;
}

.rahmen {
background-color: #000000;
padding: 1%;
}

.innen {
background-color: #ffffff;
width: 100%;
}
<div class="aussen">
  <div class="rahmen">
    <div class="innen">Inhalt 1</div>
  </div>
</div>

<div class="aussen">
  <div class="rahmen">
    <div class="innen">Inhalt 2</div>
  </div>
</div>

Das ist natürlich ziemlich viel Code, nur um zwei Elemente mit einem Rahmeneffekt nebeneinander zu positionieren. Außerdem stoßen die Inhalte bei dieser Variante direkt an den "Rahmen". Um auch hier einen Innenabstand festzulegen, müsste ein weiteres DIV-Element in den Container mit der Klasse .rahmen platziert werden und den Inhalt müsste man in diesem Element platzieren. Somit hätte man drei zusätzliche Container, nur um gewisse Abstände und einen Rahmeneffekt zu erhalten, was nicht dem Sinn einer klar strukturierten Website entspricht.