Obwohl wir heute mittels CSS viele Arten von Formen darstellen können, denken und gestalten wir immer noch in Rechtecken. Mit der Benutzung von CSS-Shapes ändert sich das.
Die Darstellung von abgerundeten Ecken, Kreisen, Dreiecken und selbst Polygonen ist schon länger kein technisches Problem mehr. Allerdings bleibt das Gefühl, als ob das Orchester nur mit halber Besetzung spielt – denn:
Diese Formen beeinflussen nicht den Textfluss um sie herum – die eigentliche Box bleibt viereckig.
Raus aus der Box: Mehr Freiräume für die Gestaltung von Webseiten mit CSS-Shapes
Das Auge liest mit: Das Layout einer Webseite könnte viel ausdrucksvoller sein, wenn der Textfluss sich an den Formen orientieren würde, wie es in Druckerzeugnissen üblich ist – und hier kommt die CSS-Shape-Spezifikation ins Spiel:
Kurz gesagt können mit CSS-Shapes geometrische Formen festgelegt werden, um die der Text fließt:
Wie funktioniert das?
Mittels CSS-Shapes werden Formen in einfacher und wiederverwendbarer Weise definiert.
Wichtig ist, dass die Platzierung der Box den benachbarten Text „verdrängt“, was mit der CSS-Auszeichnung „float“ erreicht wird. Die Fließrichtung wird natürlich übernommen.
Der umfließende Inhalt orientiert sich am Box-Model des Shape-Elements, wobei der Standardwert „margin-box“ bedeutet, dass sich Größenangaben inklusive ihres Abstands („margin“) zum umfließenden Text verstehen. In den folgenden Beispielen beziehe ich mich immer auf „margin-box“, wenn nicht anders beschrieben.
Der Formentyp wird von vier Funktionen definiert:
- circle()
- ellipse()
- inset()
- polygon()
Eine runde Sache: Kreise (shape-outside: circle)
Im oberen Beispiel habe ich – Überraschung! – die circle-Funktion verwendet.
Das HTML/CSS sieht dann im einfachsten Fall so aus:
<div class="outer-box"> <div class="box circle"> <img src="dist/img/ic_smiy_Brille.png" class="img-responsive"> </div> <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p> </div>
.circle { shape-outside: circle(50%); width: 150px; float: left; margin-right: 15px; }
Die Box mit dem Kreissymbol (hier könnte genauso gut ein Bild stehen) floatet nach links und der Paragraphen-Content fließt um diese Box. Ein „margin-left“ hält den Text auf Abstand. Das ist soweit nichts Neues.
Mit der CSS-Eigenschaft „shape-outside: circle(50%)“ lege ich nun den Bereich fest, um den der Text fließt. Anstatt des Werts „50%“ könnte ich genauso gut einen Pixelwert benutzen. In diesem Fall wären das die Hälfte des Kreisumfangs, also 75px.
Die Eigenschaft „shape-outside“ lässt noch mehr Parameter zu, mit denen wir zusätzlich Kontrolle über das Layout haben. Nehmen wir an, wir möchten erreichen, dass der Text ein wenig weiter links jenseits der Senkrechttangenten des Kreises beginnt, also so:
Dazu gebe ich der Kreisbox einen margin-top-Wert von 25px, was ungefähr meiner Zeilenhöhe entspricht. Nun müssen die Shape-Koordinaten angepasst werden. Diese orientieren sich an den margin-Werten der Box:
.set-shape-coordinates { margin: 25px 15px 0 0; shape-outside: circle(50% at 50% 100px); float: left; }
Die Hälfte des Kreisumfangs ist in unserem Fall 75px oder eben 50%. Der erste Wert nach dem „at“ bestimmt die Positionierung der Form nach rechts und bekommt ebenfalls den Wert 50%. Die vertikale Koordinate muss um den margin-top-Wert verschoben werden, in unserem Fall also 75px (Kreisumfang/2) + 25px(margin-top-Wert) = 100px.
Ein prima Anwendungsbeispiel für Shapes mit circle stellt Erik Meyer auf „A List Apart“ vor.
Das Prinzip hinter „shape-outside“
Um das Prinzip besser zu verstehen, müssen wir eine virtuelle Box um das Element vorstellen, die das Koordinatensystem zur Zeichnung und Positionierung der Form festlegt. Der Ursprung des Koordinatensystems befindet sich in der oberen linken Ecke, wobei die X-Achse nach rechts zeigt und die Y-Achse nach unten zeigt.
Der Shape-Bereich erstreckt sich bis zu den äußeren Kanten der Box, die durch die Margin-Eigenschaft definiert ist. Zur Erinnerung: Die Standardreferenzbox für eine Form hat „margin-box“ als Box-Modell.
Unbekannte Flugobjekte: Ellipsen (shape-outside: ellipse)
Die ellipse()-Funktion funktioniert im Prinzip so wie die circle()-Funktion, allerdings nimmt sie zwei Parameter entgegen. Man kann den Effekt für viele Formen benutzen, wenn deren Outline annähernd elliptisch ist.
Im oberen Beispiel habe ich die obere Position mittels der CSS calc()-Funktion um 5px nach unten verschoben, um einen schöneren Umfluss zu haben.
.ellipse { margin-right: 15px; shape-outside: ellipse(50% 50% at 50% calc(50% + 5px)); float: left; }
Die Werte für die X-und Y-Achsen können übrigens auch mit Keywörtern definiert werden:
Das Schlüsselwort „farthest-side“ bestimmt den Punkt, der am weitesten von der Strecke Ellipsenmitte bis Boxkante entfernt ist, „closest-side“ bestimmt den kürzesten Abstand:
.ellipse { margin-right: 15px; shape-outside: ellipse(closest-side farthest-side at 50% 50%); float: left; }
In allen vier Ecken soll Liebe drin stecken: Inset (shape-outside: inset)
Mittels der Funktion „inset()“ kann eine rechteckige Form erzeugt werden.
Moment – geht es nicht bei CSS-Shapes gerade darum, aus dem rechteckigem Boxenknast auszubrechen? Allerdings kann man mit „inset“ und „round“ den Text sanft um abgerundete Ecken fließen lassen. Das sieht dann zum Beispiel so aus:
.inset { margin-right: 15px; shape-outside: inset(0px 0px 0px 0px round 50px); float: left; }
Fast den gleichen Effekt kann man auch mit „shape-outside: border-box;“ erzeugen, allerdings referenzieren wir dann auf einen anderen Boxmodelltyp, nämlich border-box. Dann hat konsequenterweise der margin-right-Wert keine Wirkung mehr. Letztendlich bestimmt der Anwendungsfall, welche Methode man benutzt:
div.box.border-radius { background: lime; width: 150px; height: 100px; border-radius: 40px; float: left; shape-outside: border-box; margin-right: 15px; // Obsolet: Hat keine Wirkung }
Ecken und Kanten: Polygone (shape-outside: polygon)
Die Funktion polygon() benutzen wir, um eine eigene Form mit mehreren Knotenpunkten zu erzeugen. Die Verbindungslinien zwischen den einzelnen Punkten ist immer gerade, es ist also nicht möglich, eine Bezierkurve herzustellen. Um annähernd eine Kurve zu visualisieren, muss man genug Knoten setzen.
.polygon { float:left; shape-outside: polygon(0 0, 90% 0, 100% 40%, 40% 50%, 90% 100%, 0 100%); }
Responsivität
Einfache Formen, wie Kreise oder Rechtecke stellen keine besondere Herausforderung an die responsive Darstellung dar, weil die Werte nicht pixelgebunden sind, sondern prozentual definiert werden können.
Bei Polygonen sieht das je nach Komplexität der Form anders aus, hier ist es eventuell nötig, mit Pixelwerten zu arbeiten, die dann pro Breakpoint definiert werden müssen.
Browser-Support/Polyfills/Fallback
Jeder Frontend-Entwickler weiß, dass nach dieser Überschrift ein trauriges Kapitel beginnt. Momentan unterstützen nur Chrome, Safari, IOS Safari und Opera die Definition*.
Es gibt javascriptbasierte Polyfills, die ich allerdings nicht getestet habe. Ich würde nach dem Prinzip des „Progressive Enhancement“ vorgehen und in Browsern, die die Definition nicht unterstützen, komplett auf das Feature verzichten.
Mittels Feature-Detection-Tools wie „Modernizr“ oder „CSS Feature Queries“ lassen sich Fallbacks für die Hinterwäldlerbrowser definieren. Achtung bei „CSS Feature Queries“ – auch diese werden in einigen Browsern noch nicht unterstützt (yeah…).
* (Quelle: https://caniuse.com/#search=CSS-Shapes, Stand: 17.04.2017)
Weiterführende Links
In einem zweiten Teil habe ich über CSS-Shapes mit Bildern geschrieben.
https://www.w3.org/TR/css-shapes-1/
https://developer.mozilla.org/de/docs/Web/CSS/shape-outside
http://maddesigns.de/css3-shapes-2451.html
https://www.html5rocks.com/en/tutorials/shapes/getting-started/