CSS position-Einmaleins [A List Apart]

Der englischsprachige Originalartikel von Noah Stokes ist am 16. November 2010 im A List Apart Magazine unter dem Titel CSS Positioning 101 erschienen.

Wenn du ein Frontend-Entwickler oder ein codeliebender Designer bist, sind CSS-basierte Layouts das Herzstück deiner Arbeit. Für einige wird es eine Auffrischung für andere ein a-ha-Erlebnis sein: Lass uns die CSS-Eigenschaft position in Augenschein nehmen um zu sehen, wie wir sie zur Erstellung von standardkonformen, tabellenfreien CSS-Layouts nutzen können.

Positionierung ist alles

CSS-Positionierung wird oft falsch verstanden. Um in Eile Bugs zu beheben, weisen wir manchmal Selektoren verschiedene Werte für position zu, bis wir funktionierende Werte finden. Das ist ein mühsamer Prozess, der eine Weile funktionieren mag. Er hält uns aber davon ab zu verstehen, warum zum Beispiel die Deklaration position: relative einen Fehler in unserem Layout behebt.

Meine Hoffnung ist, dass wir die Werte der Eigenschaft position und ihr Verhalten lernen und noch wichtiger, verstehen wie die Werte unser Markup beeinflussen. Die CSS-Spezifikation bietet uns fünf position-Eigenschaften: static, relative, absolute, fixed und inherit. Jeder Wert dient einer bestimmten Zweck. Diesen Zweck zu verstehen ist der Schüssel zur Beherschung von CSS-basierte Layouts.

Bleibe im Fluss

Lasst uns zuerst einen Schritt zurück treten, um einen Blick auf die Welt zu werfen, in der wir arbeiten. Ähnlich wie in unserer realen Welt arbeiten wir im CSS innerhalb von Grenzen. Im CSS werden diese Grenzen normal flow (nicht manipulierte Abfolge) genannt. Der CSS-Spezifikation 2.1 folgend:

Elemente im normal flow stehen im Zusammenhang mit Formatierungen: Sie können Block- oder Inline-Elemente sein, allerdings nie beides gleichzeitig. Mit block ausgezeichnete Elemente sind Teil des mit block formatierten Umfeldes. Mit inline ausgezeichnete Elemente sind Teil des mit inline formatierten Umfeldes.

Stelle dir das Element, wie es die Spezifikation beschreibt, als Bauklotz vor – ähnlich denen, mit denen du als Knirps gespielt hast. Nun stelle dir den normal flow als etwas ähnliches wie das Gesetz der Schwerkraft vor.
Der normal flow des Dokuments ist die Stapelreihenfolge der Elemente von oben nach unten, in der gleichen Reihenfolge, in der sie in deinem Markup erscheinen.

Vielleicht erinnerst du dich, Buchstaben-Bauklötze zu gigantischen Türmen zusammengebaut zu haben: Der normal flow unterscheidet sich kaum von diesen von der Schwerkraft zusammengehaltenen Bauklötzen. Als Kind hast du einen Klotz auf den anderen gesetzt, im Markup schreibst du ein Element nach dem anderen.

Wozu du als Kind nicht in der Lage warst, war den Bauklötzen Eigenschaften zu geben, die sie gegen das Gesetz der Schwerkraft immun machten. Plötzlich erscheint dir CSS viel cooler als diese alphabetischen Bauklötze.

Static oder relative — hier bleibt alles beim alten

Die Werte static und relative der Eigenschaft position verhalten sich wie unsere Kindheits-Bauklötze – sie stapeln sich, wie du es erwartest. Beachte, dass static der Standardwert für position ist, solltest du keinen anderen Wert zuweisen.

Wenn du drei statisch positionierte Elemente in deinem Code hast, wird sich einer über den nächsten stapeln, genau wie du es erwartest. Lass uns einen Blick auf ein entsprechendes Beispiel werfen:

#box_1 {
position: static;
width: 200px;
height: 200px;
background: #ee3e64;
}

#box_2 {
position: static;
width: 200px;
height: 200px;
background: #44accf;
}

#box_3 {
position: static;
width: 200px;
height: 200px;
background: #b7d84b;
}

In Beispiel A kannst du drei Elemente gestapelt zu einem einfachen Turm sehen. Faszinierend oder etwa nicht? Das ist das Blockbau-Einmaleins – Glückwunsch!

Du kannst den static-Wert für einfache, einspaltige Layouts nutzen, in denen jedes Element oberhalb des nächsten platziert sein soll.

Wenn du anfangen möchtest diese Elemente umherzuschieben, indem du Eigenschaften wie top, right, bottom, and left vergibst, wirst du kein Glück haben. Diese Eigenschaften sind nicht verfügbar für ein static positioniertes Element. De facto kann ein static positioniertes Element kein neues Koordinatensystem für Kind-Elemente erzeugen. Warte, was? Bei Koordinatensystem habe ich dich abgehängt? Lass es mich mit dem weiteren Wert relative erklären.

Realtiv positionierte Elemente verhalten sich ähnlich statisch positionierten Elementen: sie arbeiten gut mit anderen zusammen, stapeln sich unkompliziert und verursachen keinen Aufstand. Schwer zu glauben, stimmt’s? Schauen wir nochmal auf unser vorheriges Beispiel. Diese Mal weisen wir den Wert relative zu:

#box_1 {
position: relative;
width: 200px;
height: 200px;
background: #ee3e64;
}

#box_2 {
position: relative;
width: 200px;
height: 200px;
background: #44accf;
}

#box_3 {
position: relative;
width: 200px;
height: 200px;
background: #b7d84b;
}

Beispiel B beweist, dass sich relativ positionierte Elemente zunächst exakt wie statisch positionierte Elemente verhalten. Was du vielleicht nicht weißt, ist, dass Elemente mit position: relative wie Clark Kent sind — sie verstecken weit größere Kräfte als ihre statisch positionierten Elemente.

Für den Anfang kann ihre Position feinjustiert werden, indem sie mit Versatz-Eigenschaften ergänzt werden: top, right, bottom und left.
Benutzen wir das vorherige Beispiel erneut und ergänzen eine versetzte Position beim Selektor #box_2:

#box_2 {
position: relative;
left: 200px;
width: 200px;
height: 200px;
background: #44accf;
}

Beispiel C zeigt diese erweiterte relative Positionierung in Aktion. Unsere drei Blöcke sind gestapelt wie gehabt, aber dieses Mal ist der blaue Block (#box_2) 200 Pixel von links herausgeschoben. Das ist der Moment, wo wir anfangen das Gesetz der Schwerkraft unserem Willen zu unterwerfen.

Der blaue Block befindet sich immer noch in der normalen Abfolge des Dokuments — die Elemten stapeln sich aufeinander — aber schau dir den grünen Block (#box_3) unten an. Er sitzt unterhalb des blauen Blocks, obwohl sich der blaue Block nicht direkt über ihm befindet.

Wenn du eine Versatz-Eigenschaft benutzt, um relativ positionierte Elemente zu verschieben, beeinflusst das nicht die nachfolgenden Elemente. Die grüne Box ist immer noch so positioniert als wäre die blaue Box in ihrer urspünglichen, nicht-versetzten Position. Versuch das mal mit deinem Turm aus Bauklötzen.

Ein Koordinatensystem für Kind-Elemente zu ereugen ist eine weitere herausragende Möglichkeit von realtiv positionierten Elementen. Das Koordinatensystem ist ein Referenz-Punkt für Versatz-Eigenschaften. Erinner dich an Beispiel C: Unser blauer Block sitzt nicht innerhalb eines anderen Elements. Also benutzt es das Koordinatensystem des Dokumentes selbst, um sich 200 Pixel vom linken Dokumentenrand wegzuschieben.

Wenn wir das Element #box_2 stattdessen innerhalb des Elements #box_1 platzieren, bekommen wir ein anderes Ergebnis: #box_2 positioniert sich dann relativ zum Koordinatensystem von #box_1. Für das nächste Beispiel werden wir nichts am CSS ändern. Stattdessen passen wir das HTML an und verschieben #box_2 in #box_1:

<div id="box_1">
   <div id="box_2"></div>
</div>

Beispiel D zeigt das Ergebnis unseres neuen Markups. Wegen des jetzt neu zu benutzenden Koordinatensystems bemisst der blaue Block seinen 200 Pixel Versatz in Relation zum linken Rand des roten Blocks (#box_1) anstatt zum linken Rand des Dokuments.

Diese Praxis findet häufiger Anwendung bei Elementen mit dem Wert position: absolute — früher hast du dir gewünscht Bauklotz-Türme auf diese Weise bauen zu können.

Absolute — überall, jederzeit

Wenn sich der Wert relative wie Supermann verhält, dann spiegelt der Wert absolute Inception wider — ein Ort, an dem du deine eigene Welt erschaffst.

Anders als die Werte static und relative wird ein absolut positioniertes Element aus dem normal flow entfernt. Das bedeutet, dass du es überall platzieren kannst: Es beeinflusst selber keine und wird selber nicht beeinflusst durch andere Elemente aus der regulären Abfolge. Stelle dir vor, das Element hätte ein großes Klettband an der Rückseite. Sag ihm, wo es sich festkletten soll, und es bleibt dort angeklettet.

Genau wie relativ positionierte Elemente reagieren die absolut positionierten bei ihrer Positionierung auf Versatz-Eigenschaften: Du kannst einem Element top: 100px und left: 200px zuweisen und es wird sich exakt 100 Pixel vom oberen und 200 Pixel vom linken Rand des übergeordneten, positionierten Elements entfernt platzieren. Lass uns ein Beispiel mit vier Elementen anschauen:

#box_1 {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 200px;
background: #ee3e64;
}

#box_2 {
position: absolute;
top: 0;
right: 0;
width: 200px;
height: 200px;
background: #44accf;
}

#box_3 {
position: absolute;
bottom: 0;
left: 0;
width: 200px;
height: 200px;
background: #b7d84b;
}

#box_4 {
position: absolute;
bottom: 0;
right: 0;
width: 200px;
height: 200px;
background: #ebde52;
}

Beispiel E zeigt 4 Kästen, jeder in einer anderen Ecke des Browsers. Weil wir position den Wert absolute zugewiesen haben, haben wir im Grunde jeden Kasten in einer Ecke des Browserfensters festgeklettet. Wenn du das Browserfenser in seiner Größe veränderst, bleiben die Kästen in ihren Ecken. Wenn du den Browser verkleinerst bis sich die Kästen überlagern, wirst du merken, dass sie überhaupt nicht miteinander interagieren — weil sie sich eben nicht mehr im normal flow befinden.

Genau wie relativ positionierte Elemente erzeugen absolut positionierte Elemente ein neues Koordinatensystem für ihre Kind-Elemente. Beispiel F erweitert Beispiel E um ein oranges Element, das inhalb jedes Kastens platziert wurde. Wie du sehen kannst, hält sich jeder orangene Kasten an die versetzten Koordinaten seines Eltern-Elements.

Anders als alle anderen Werte für die position-Eigenschaft ist der Wert absolute unschlagbar, wenn es um die Nutzung der Versatz-Eigenschaften geht. Benutzt du zwei oder alle vier Versatz-Eigenschaften, kannst du das Element ohne die Definition von Weite (width) und Höhe (hight) beliebig strecken. Es wird dann nur durch sein Eltern-Element oder das Dokument selbst beschränkt. Lass uns das ansehen — betrachte den folgenden Code:

#box_a {
position: absolute;
top: 10px;
right: 10px;
bottom: 10px;
left: 10px;
background: red;
}

#box_b {
position: absolute;
top: 20px;
right: 20px;
bottom: 20px;
left: 20px;
background: white;
}

In Beispiel G haben wir die Grenzen der Kästen alleine mit einer Versatz-Anweisung von 10 Pixeln vom Dokumentenrand versehen. Die Kästen bewegen sich völlig flüssig auch wenn das Browserfenster in seiner Größe variiert wird — alles alleine mithilfe der absolute-Positionierung und Versatz-Anweisungen.

In einem weiteren Beispiel erstellen wir ein zweispaltiges Layout, das die gesamte Höhe des Dokuments füllt. Hier folgt das CSS:

#box_1 {
position: absolute;
top: 0;
right: 20%;
bottom: 0;
left: 0;
background: #ee3e64;
}

#box_2 {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 80%;
background: #b7d84b;
}

Beispiel H zeigt ein zweispaltiges, den ganzen Bildschirm einnehmendes Layout. Auch wenn es nicht der beste Weg ist ein zweispaltiges derartig umzusetzen, zeigt es doch die umfangreichen Möglichkeiten, die die absolute-Positionierung in sich trägt. Mit ein wenig kreativem Geist lassen sich einige nützliche Anwendungen für position: absolute finden. Ähnliche Tricks nutzen lediglich ein Versatz-Eigenschaft, zum Beispiel:

#box_1 {
width: 200px;
height: 200px;
background: #ee3e64;
}

#box_2 {
position: absolute;
left: 100px;
width: 200px;
height: 200px;
background: #44accf;
}

Schau dir in Beispiel H2 den blauen Kasten (#box_2) an. Beachte, dass ich nur einen Versatz left: 100px definiert habe. Das erlaubt dem #box_2-Element seinen oberen Rand zu behalten, sich aber immer noch 100 Pixel vom linken Rand wegzubewegen.

Würden wir einen zweiten Versatz für top definieren, könnten wir sehen, dass unser blauer Kasten (#box_2) an den oberen Rand des Dokuments gezogen werden würde. Schau dir das in Beispiel H3 an:

#box_2 {
position: absolute;
top: 0;
left: 100px;
width: 200px;
height: 200px;
background: #44accf;
}

fixed — immer genau da

Ein Element mit position: fixed teilt alle Regeln mit absolut positionierten Elementen, außer dass der Viewport (das Browserfenster, der Bildschirm mobiler Geräte) die Relation für die Positionierung liefert unabhängig davon, ob Elternelemente vorhanden sind. Außerdem scrollt ein fixiertes Element nicht mit dem Dokument. Es bleibt… naja, eben fixiert. Lass uns ein Beispiel ansehen:

#box_2 {
position: fixed;
bottom: 0;
left: 0;
right: 0;
}

Beispiel I zeigt einen Footer mit Hinweisen zum Copyright und der Anweisung position: fixed. Wenn du scrollst fällt dir auf, dass sich der Footer nicht bewegt.
Beachte, dass die Versatz-Eigenschaften left und right den Wert 0 erhalten haben. Weil sich position: fixed ähnlich wie position: absolute verhält, können wir das Element über den gesamten Viewport strecken, während es von bottom: 0; am unteren Rand festgehalten wird.
Sei aber vorsichtig bei der Benutzung von position: fixed: In älteren Browsern ist die Unterstützung allenfalls löchrig. Zum Beispiel rendern ältere Versionen des Internet Explorers fixed-positionierte wie static-positionierte Elemente. Und du weißt, dass sich static-positionierte Elemente nicht wie fixed-positionierte benehmen, stimmt’s?
Wenn du dennoch fixed-positionierte Elemente in einem Layout benutzen möchtest, gibt es verschiedene Lösungen (en), damit sich diese Elemente auch in Browsern ohne entsprechende Unterstützung des fixed-Wertes erwartungsgemäß verhalten.

Inherit — etwas für nichts

Wie ich es am Anfang dieses Artikels bereits erwähnte, gibt es fünf Werte für die Eigenschaft postion. Der fünfte Wert lautet inherit. Bekommt ein Element diesen Wert zugewiesen, erbt es den Wert der Positionierung von seinem Eltern-Element.

Kind-Elemente erben die Werte der Eigenschaft position nicht automatisch von ihren Eltern. Wird position nicht definiert, wird dem Element der Wert static zugewiesen. Letztendlich kannst du einem Kind-Element entweder inherit oder den Wert des Eltern-Elements zuweisen und erhälst das gleiche Ergebnis.

In Aktion

Lauter Theorie, wo bleibt die Praxis? Lass uns ein reales Beispiel anschauen, ein Layout, das alle Werte für position zum Einsatz bringt: Beispiel J zeigt ein typisches Webseiten-Layout mit Header (Kopfbereich), Navigation, Content (Inhalt) und Footer (Fußbereich).

Lass uns alle Elemente durcharbeiten und die gewählten Werte für position und den Grund der Wahl diskutieren. Fangen wir mit dem #container Element an. Es dient ganz einfach als umklammerndes Element, das ich benutze, um den gesammten Inhalt der Website im Viewport zu zentrieren.

Die Navigation (#nav) ist das erste Element innerhalb des #container-Elements. Der Eigenschaft position wurde kein Wert zugewiesen, damit kommt der Default-Wert static zum tragen. Das ist gut so, weil wir dieses Element nicht versetzen möchten und es auch kein neues Koordinatensystem erzeugen muss.

Unser nächstes Element #content soll seinen Kind-Elementen hingegen ein Koordinatensystem zur Verfügung stellen, also geben wir der Eigenschaft position den Wert relative:

#content {
position: relative;
padding: 20px 250px 60px 20px;
background: #fff;
}

Weil wir hier keine Versatz-Eigenschaften einsetzen, hat die Angabe keinen Einfluss auf das #content-Element selbst. Uns kommt es nur auf das erzeugte Koordinatensystem für das nachfolgende Element #callout an:

#callout {
position: absolute;
top: 100px;
bottom: 100px;
right: -80px;
width: 210px;
padding: 0 20px;
border-top: 5px solid #f95b34;
background: #fa8366;
}

Das #callout-Element erhält position: absolute und weil bei seinem Elternelement ebenfalls die Position definiert ist, orientieren sich die Versatz-Eigenschafen an dessen Koordinaten. Es erhält einen negativen Versatz von 80 Pixeln nach rechts und schiebt sich so aus seinem umgebenden Elternelement heraus.

Zusätzlich nutze ich hier eine der interessanteren Möglichkeiten der absoluten Positionierung: Mit der Zuweisung eines Versatzes von 100 Pixeln für top und bottom strecke ich das #callout-Element über fast die gesamte Höhe des #content-Elements.
Weil das #callout-Element den Wert absolute für seine Position erhalten hat, beeinflusst es nicht andere Elemente. Daher mussten wir dem #content-Element einen rechtsseitigen Wert für padding zuweisen, damit dessen Inhalte nicht unter dem #callout-Element verschwinden. Ein Wert von 250 Pixeln stellt sicher, dass der gesamte Inhalt sichtbar bleibt.

Um den Ring zu schließen haben wir einen Footer mit position: fixed hinzugefügt und ihn so am unteren Ende der Seite fixiert. Während wir scrollen, bleibt unser Footer an Ort und Stelle.
Genau wie wir ein rechtsseitiges padding für das #content-Element definieren mussten, damit seine Inhalte nicht unter dem #callout-Element verschwinden, mussten wir auch ein unteres padding für das #content-Element hinzufügen, damit nichts vom Footer überlagert wird. 60 Pixel reichen aus, damit keine Inhalte verschwinden, wenn das Dokument bis nach unten gescrollt wird.

Nun haben wir ein nettes, einfaches Layout mit Navigation, Inhalten, zusätzlichem Informationskasten und Footer, bei dem wir die Werte static, relative, absolute und fixed eingesetzt haben. Weil wir den Wert fixed benutzt haben, sollten wir entsprechende Techniken (en) einsetzen, um die korrekte Funktionalität in älteren Browsern sicher zu stellen.

Zusammenfassung

Mit den weitgreifenden Möglichkeiten der Eigenschaft position kannst du viele verschiedenen Layouts selbstsicher und erfolgreich umsetzen.

Glücklicherweise werden 80% der Werte für position exzellent sowohl von alten als auch von modernen Browsern unterstützt. Beim Wert fixed solltest du aber vorsichtig sein.

Grundlegendes Verständnis für die Werte der Eigenschaft position geben dir ein Fundament für solide CSS-basierte Layouts, die nur noch durch deine Vorstellungskraft begrenzt sind. Hoffentlich sind deine Tage des Ratens der Werte für position beim Bug-fixing in letzer Minute nun gezählt.

Übersetzt mit der Erlaubnis von A List Apart Magazine und dem Autor.
Translated with the permission of A List Apart Magazine and the author.

Keine Kommentare

Bis jetzt gibt es noch keine Kommentare.

RSS-Feed für Kommentare dieses Beitrags

Die Kommentar-Funktion ist momentan leider deaktiviert.