3. Jan 2023
Lesedauer 12 Min.
Ziemlich schräg
CSS-Techniken für schräge Elemente
Elemente auf Webseiten müssen nicht immer rechtwinklig sein – für Schrägen existieren verschiedene Techniken.

Standardmäßig sind Elemente auf Webseiten rechteckig und senkrecht oder horizontal ausgerichtet: Texte in Absätze und Überschriften werden in westlichen Sprachen senkrecht untereinander angeordnet, Bilder befinden sich auf derselben Linie wie Text, Raster über Gridlayout sind ebenfalls rechteckig etc. Eine probate Auflockerung dieses Schemas ist es, schräge Elemente oder Hintergründe zu integrieren. So lassen sich im Hero-Bereich Schrägen definieren oder man verwendet Schrägen nur bei kleineren Komponenten. Dazu ein paar Beispiele aus dem Web:Wie aber lassen sich Schrägen mit CSS umsetzen? Dafür stehen mehrere Techniken zur Auswahl – Sie können Elemente mit transform drehen oder verzerren und erhalten dadurch eine Schräge, auch clip-path erlaubt das Ausschneiden von Elementen und damit die Erzeugung von Schrägen. Dann wäre da außerdem noch die Eigenschaft border, die bei geschicktem Einsatz ebenfalls für Schrägen sorgen kann. Auch mit Hintergrundbildern lassen sich Schrägen erzeugen und solche Bilder können mit CSS generiert oder mit SVG umgesetzt werden.

Beispielanwendungen:Schrägen bei moderncss.dev(Bild 1)
Maurice
Der Artikel stellt die einzelnen Techniken vor und zeigt einige Anwendungen. Außerdem erfahren Sie, was zum Beispiel bei Schatten zu beachten ist.
Transformationen
Für die Erzeugung von Schrägen kommt vielen wahrscheinlich als erstes die Eigenschaft transform in den Sinn, die allerdings einige Besonderheiten hat und auch mit ein paar Neuerungen aufwartet.Bei transform können Sie mit diversen Funktionen die Transformationen bestimmen: So lassen sich Elemente drehen (rotate()), verschieben (translate()) und skalieren (scale()). Mit skew() ist auch eine Verzerrung möglich. Außerdem kann man einen Teil der Funktionen nur auf die x- oder nur auf die y-Achse beschränken, zum Beispiel translateX() oder scaleX(), und es sind auch Transformationen im 3d-Raum möglich. Eine ganz genaue exakte Steuerung der Transformation mit allen Parametern erlaubt die matrix()-Funktion für diejenigen, die im Mathematikunterricht gut aufgepasst haben. Mit transform-origin wiederum lässt sich beispielsweise der Drehpunkt bei einer Rotation festlegen. So definiert etwa transform-origin: 0 100%, dass ein Element um die linke untere Ecke gedreht werden soll.Und es gibt zusätzliche Neuerungen: Für drei der Transformationsfunktionen wurden inzwischen individuelle Eigenschaften eingeführt. Die Regel transform: rotate(30deg) translate(1rem, 2rem) scale(1.2);lässt sich auch so schreiben:rotate: 30deg;
translate: 1rem 2rem;
scale: 1.2;
Für die anderen Transformfunktionen wie skew() und matrix() sind derzeit noch keine individuellen Eigenschaften vorgesehen. Die individuellen Eigenschaften machen bei Änderungen oder bei Animationen das Handling einfacher. Denn bei der Modifikation von Transformationen tritt ein bestimmtes Problem auf. Dazu ein Beispiel:
.el {
transform: rotate(30deg);
}
.el:hover {
transform: scale(1.3);
}
Hier wird ein Element um 30deg gedreht. Beim Hovern soll das gedrehte Element vergrößert werden. Allerdings setzt die Angabe transform: scale(1.3) die Drehung auf 0. Wenn die Drehung beibehalten werden soll, muss sie ein zweites Mal angegeben werden:
.el {
transform: rotate(30deg);
}
.el:hover {
transform: rotate(30deg) scale(1.3) ;
}
Das geht durch die einzelnen Transformationseigenschaften einfacher. Der Code lässt sich dann auch schreiben als:
.el {
rotate: 30deg;
}
.el:hover {
scale: 1.3;
}
Die individuellen Transformationseigenschaften werden von allen modernen Browsern unterstützt, aber natürlich ist die Unterstützung für die ursprüngliche Syntax noch besser – und es gibt nicht für alle Eigenschaften die individuellen Angaben.Für Schrägen bieten sich die Eigenschaft skew() oder auch rotate() an. Zusätzlich muss man meist noch mit translate() und scale() operieren, um den gewünschten Effekt zu erreichen. Zwei Herausforderungen ergeben sich nämlich bei Transformationen:
- Wenn man ein Rechteck in einem Element dreht, ragt es über die Ecken des Elternelements heraus, weil die Diagonale immer länger ist als die längste Seite. Wenn das gedrehte Element das Elternelement trotzdem noch ausfüllen soll, muss es skaliert werden und soll oft zusätzlich verschoben werden. Auch kann es notwendig sein, herausragende Teile mit overflow: hidden beim Elternelement abzuschneiden.
- Mitgehangen, mitgefangen: Kindelemente werden ebenfalls transformiert, beispielsweise gedreht. Wenn das nicht gewünscht ist, muss man die Elemente wieder in die entgegengesetzte Richtung drehen, um die ursprüngliche Drehung aufzuheben.
Gedrehtes Bild – gerade bei Hover
Einen netten Effekt hat die Website Smashing Magazine bei den Autorenbildern integriert. Diese stehen in einem gekippten Quadrat, das sich beim Hovern gerade aufrichtet. Und der Clou dabei: Die Bilder sind auch im gekippten Quadrat gerade. Ein etwas vereinfachtes Beispiel macht das Grundprinzip deutlich (Bild 2).
Gerades Bildin schrägem Kasten, das beim Hovern wieder gerade wird(Bild 2)
Maurice
Folgender HTML-Code dient als Basis: Es wird ein figure-Element verwendet, in dem sich ein div-Container mit dem eigentlichen Bild befindet:
<figure class="bio-image">
<div class="bio-image-wrapper">
<img class="bio-image-image" src="katze.jpg"
alt="Katze">
</div>
</figure>
Zum CSS-Code: Das figure-Element gibt die Ausmaße des Bilds vor – hier 12rem mal 12rem. Außerdem wird der Außenabstand auf 0 gesetzt. Das ist notwendig, da figure standardmäßig einen margin hat – so ist es im Browserstylesheet definiert:
.bio-image {
margin: 0;
width: 12rem;
height: 12rem;
}
Das div-Element im figure-Element wird nun gedreht und zusätzlich ein bisschen verkleinert und verschoben. overflow: hidden sorgt dafür, dass das Bild nicht über den umfassenden Container hinausragen kann. Die transition bereitet schon die Animation für den Hoverzustand vor. Da sie beim Hovern und beim Verlassen des Bereichs angewendet werden soll, wird sie beim Ursprungszustand notiert:
.bio-image-wrapper {
border: solid rgb(18, 79, 159);
background: rgb(18, 79, 159);
transform: scale(.84) translateX(15%) rotateZ(-11deg);
transform-origin: 0 100%;
transition: transform .2s ease-out;
overflow: hidden;
}
Nun zu den Formatierungen des Bildes selbst. Es soll das Element ganz ausfüllen, dafür wird für width und height der Wert 100% angegeben. Damit das Bild nicht verzerrt wird, erhält object-fit die Angabe cover:
.bio-image-image {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
Standardmäßig sind Kindelemente innerhalb eines transformierten Elements ebenfalls transformiert, das Bild soll aber gerade dargestellt werden. Dafür müssen die Transformationen des Elternelements aufgehoben werden: Das Elternelement war verkleinert (0.84), das Kindelement muss also vergrößert werden (1.2); das Elternelement war um 11deg nach links gedreht (-11deg), das Kindelement muss also um dieselbe Gradanzahl nach rechts gedreht werden (11deg). Zusätzlich wird auch hier eine transition definiert:
transform: scale(1.2) rotateZ(11deg);
transition: transform .2s ease-out; }
Damit ist der gewünschte Effekt erreicht: Das Bild ist gerade und befindet sich in einem gedrehten Element. Beim Hovern soll die Komponente in der nicht-gedrehten Form dargestellt werden, das heißt, jede vorher definierte Drehung bei den figure-/img-Elementen muss wieder aufgehoben werden:
.bio-image:hover .bio-image-wrapper {
transform: scale(.84) translateX(15%) rotateZ(0);
}
.bio-image:hover .bio-image-image {
transform: scale(1.2) rotateZ(0);
}
Für diesen auf den ersten Blick einfach wirkenden Effekt sind also vier Transformationen notwendig. An sich ist das aber ein typischer Einsatz für transform, das man gerne bei einzelnen Komponenten verwendet. Solche Animationen finden in der GPU (Graphics Processor Unit) statt, was für eine gute Performance gerade auf mobilen Geräten sorgt.Eine andere Methode zur Erzeugung von Schrägen ist es, direkt Trapeze oder Dreiecke aus Elementen auszuschneiden. Dafür kann man clip-path einsetzen.
Sichtbaren Bereich definieren
clip-path definiert den Bereich eines Elements, der sichtbar sein soll. Zur Festlegung der Form stehen Funktionen wie circle(), ellipse(), polygon() oder path() zur Verfügung. In unserem Zusammenhang relevant ist die Funktion polygon(). Bei polygon() geben Sie die gewünschten Punkte mit Komma getrennt hintereinander an.Es empfiehlt sich mit Prozentwerten zu arbeiten, die sich hier auf das Element selbst beziehen. Ein rechtwinkliges Dreieck, dessen schräge Längsseite von links oben nach rechts unten läuft, lässt sich mit clip-path: polygon(0 0, 100% 0%, 100% 100%); definieren. Die Angaben legen die einzelnen Punkte fest.Um clip-path für einen Bereich zu nutzen, der so breit ist wie der Viewport, kann man mit erzeugten Inhalten arbeiten. Es gibt dann zwei prinzipielle Möglichkeiten, die mit clip-path erzeugte Form zu nutzen. Zum einen können Sie diese Form genauso einfärben wie den Bereich, den sie schräg abschließen soll, und im Anschluss daran platzieren.Zum anderen können Sie das mit clip-path erzeugte Element so einfärben wie den allgemeinen Seitenhintergrund. Dann erzeugt die clip-path-Form sozusagen die Ausschneidung und wird auf dem Element platziert, das die Schräge unten haben soll. Man muss dabei darauf achten, dass der Textinhalt in dem dafür vorgesehenen Bereich bleibt und auch bei unterschiedlichen Viewports nicht in den abgeschnittenen Bereich fließt. Sehen wir uns das einmal praktisch an.Gehen wir davon aus, dass wir einen header haben, der mit einer Schräge enden soll. Wir wollen einen erzeugten Inhalt mit einen schrägen Bereich am Ende des header platzieren und in der Farbe des sonstigen Hintergrunds einfärben, damit es so aussieht, als wäre der header schräg abgeschnitten. Im HTML-Code (<header>Header</header>) steht der header, der unten mit einer Schräge enden soll.Formatierungen über CSS
Kommen wir zu den Formatierungen über CSS: Für body wird über eine Variable eine Hintergrundfarbe definiert. Es ist praktisch, hier mit einer Variablen zu arbeiten. Schließlich soll die mit clip-path erzeugte Form wie eine Ausschneidung aussehen und dafür benötigt sie dieselbe Farbe wie der allgemeine Hintergrund – in unserem Fall body, es könnte aber natürlich auch ein anderes Element sein:body {
--bgcolor: white;
background-color: var(--bgcolor);
}
Nun geht es an die Formatierungen für header. Dabei ist die Angabe position: relative wichtig. Diese sorgt dafür, dass der header den Positionspunkt für die Positionierung des erzeugten Inhalts mit der schrägen Form bildet. Wichtig ist auch die Variable --hoehe. Sie wird dann gleich beim erzeugten Inhalt die Höhe der Schräge bestimmen. Entscheidend ist dabei, dass der header mindestens ein padding nach unten in derselben Höhe hat. Damit ist sichergestellt, dass kein Inhalt in die Schräge läuft. Im Beispiel wird das untere padding doppelt so hoch gewählt wie die Höhe der Schräge:
header {
--hoehe: 3rem;
padding: 5rem;
background-color: gray;
padding-block-end: calc(var(--hoehe) * 2);
position: relative;
}
Es fehlt noch die schräge Form, für die ein erzeugter Inhalt genutzt wird: Diese Form soll absolut positioniert werden. Mit inset-block-end und inset-inline-start wird die Form unten links angeordnet. Statt der logischen Eigenschaften hätte man hier auch die klassischen Angaben left und bottom nutzen können. Für height, was hier ja die Höhe des Dreiecks festlegt, und für die Hintergrundfarbe werden die vorher definierten Variablen eingesetzt. Und dann fehlt nur noch die clip-path-Angabe:
header::after {
content: "";
height: var(--hoehe);
width: 100%;
position: absolute;
inset-block-end: 0;
inset-inline-start: 0;
background-color: var(--bgcolor);
clip-path: polygon(100% 0,100% 100%,0 100%);
}
Bild 3 zeigt die Schräge: Links ist der erzeugte Inhalt anders eingefärbt, damit er zu erkennen ist, rechts hat der erzeugte Inhalt dieselbe Farbe wie der body-Hintergrund. Hier sind natürlich Varianten möglich – so könnte man den Header gesamt mit clip-path bearbeiten, das heißt ein entsprechendes Trapez definieren.

Schräge Form:Schräger Abschluss mit clip-path(Bild 3)
Maurice
Schon seit langem haben Webdesigner die border-Eigenschaft mit ungewöhnlichen Angaben genutzt, um Formen wie Dreiecke zu erzeugen. Das Grundprinzip dabei: Wenn Sie an allen Seiten einer Form die Rahmenteile unterschiedlich einfärben, sehen Sie, dass die Teile schräge Abschlüsse haben. Zur Erzeugung von Formen nimmt man ein Element ohne Ausmaße, so dass nur die Rahmenteile zu sehen sind. Es lassen sich verschiedene Formen generieren, indem man einzelne Rahmenteile transparent macht und dann auch die Breite der Rahmen modifiziert. Das ist auch das Prinzip, das man zur Definition einer Schrägen benötigt.

Schrägenüber die CSS-Eigenschaft border(Bild 4)
Maurice
Sehen wir uns das Grundprinzip an. Gestyled werden mit <div class="schraeg"></div> vier div-Elemente ohne Inhalt. Vier Mal wird auf unterschiedliche Art ein Rahmen definiert – beim vierten Element ergibt sich die gewünschte Schräge (Bild 4). Beginnen wir mit einem 3rem breiten Rahmen, der an allen Seiten unterschiedlich eingefärbt ist:
.schraeg:nth-child(1) {
border-style: solid;
border-width: 3rem;
border-color: #007cff lime aqua #0e64be;
}
Damit haben wir ein vierfarbiges Element, das rechts und links ein Dreieck hat, oben und unten befinden sich andersfarbige Flächen. Wenn wir nun die Rahmenfarben überall mit Ausnahme der rechten Seite auf transparent setzen, bleibt nur das rechte grüne Dreieck übrig:
.schraeg:nth-child(2) {
border-style: solid;
border-width: 3rem;
border-color: transparent lime transparent
transparent;
}
Nun können wir die Rahmenbreiten unterschiedlich definieren. Wenn wir sie oben und links auf 0rem, aber rechts auf 10rem und unten auf 3rem setzen, erhalten wir ein rechtwinkliges Dreieck, mit einer Höhe von 3rem und bereits mit der schrägen Form:
.schraeg:nth-child(3) {
border-style: solid;
border-width: 0rem 10rem 3rem 0rem;
border-color: transparent lime
transparent transparent;
}
Damit es eine echte Schräge wird, muss jetzt nur noch der rechte Rahmen auf die richtige Länge gesetzt werden. Leider lässt sich die border-width nicht in Prozent festlegen – Prozentangaben sind bei dieser Eigenschaft nicht erlaubt. Aber man kann die Viewport-Units einsetzen, zum Beispiel vw, das sich auf die Viewport-Breite bezieht. Im Beispiel wird die Breite des Rahmenteils auf 100vw minus 4rem festgesetzt. 4rem müssen im Beispiel subtrahiert werden, da es rechts und links einen 2rem breiten Rand (margin) gibt. Gleichzeitig zeigt diese Angabe, dass man für die Rahmenbreite ebenfalls calc() nutzen kann:
.schraeg:nth-child(4) {
border-style: solid;
border-width: 0 calc(100vw – 4rem) 3rem 0;
border-color: transparent lime transparent
transparent;
}
Damit haben wir die eine Schräge, die den Viewport ausfüllt (abgesehen von margin). Diese Angaben kann man beispielsweise mithilfe von erzeugten Inhalten bei einem Element hinzufügen – so wie es bei dem Beispiel mit clip-path gezeigt wurde.
Schräge Bilder
Für Schrägen können Sie auch mit Hintergrundbildern arbeiten. Besonders flexibel sind per CSS erzeugte Hintergrundbilder. Dafür eignet sich linear-gradient(). Standardmäßig verläuft ein Farbverlauf gerade von oben nach unten, aber Sie können auch einen Winkel als ersten Parameter angeben. Mit background-image: linear-gradient(170deg, red, yellow); definieren Sie einen schrägen Farbverlauf (170deg) von Rot nach Gelb. Wenn man hinter den Farben denselben Prozentsatz angibt, wechseln die Farben an dieser Stelle abrupt:background-image: linear-gradient(170deg, red 80%,
yellow 80%);
Und schließlich kann man die zweite Farbe noch transparent setzen, dann hat man die gewünschte Schräge. Die einzelnen Schritte zur Erzeugung einer Schräge über einen linearen Farbverlauf zeigt Bild 5.

Farbverlauf:Einen Farbverlauf nutzen für Schrägen(Bild 5)
Maurice
Der harte Übergang wirkt allerdings etwas unscharf, es gibt unschöne Treppeneffekte. Eine weitere Möglichkeit besteht darin, die schräge Form über SVG umzusetzen. SVG erlaubt das Zeichnen von Formen und es steht auch ein polygon-Element zur Verfügung. Das polygon-Element definiert eine geschlossene Form, der letzte Punkt wird dabei mit dem ersten verbunden. Die Punkte werden bei dem Attribut points notiert:
<div class="schraeg">
<svg viewBox="0 0 100 100"
preserveAspectRatio="none">
<polygon points="0,100 100,0
100,100" /></svg>
</div>
Der Vorteil von SVG ist, dass es perfekt skaliert. Und für Schrägen sind nicht viele Codezeilen notwendig – im Gegensatz zu den sonst oft komplexen SVG-Dateien. Wenn man Schrägen einsetzt, muss man sich überlegen, wie sich diese verhalten sollen, wenn weniger Platz im Viewport zur Verfügung steht.Soll bei kleinerem Viewport die bildschirmfüllende Schräge weiterhin schräg sein, stehen zwei Optionen zur Auswahl: Es kann entweder die Höhe oder aber der Winkel beibehalten werden. Beim gezeigten clip-path-Beispiel ist die Höhe des schrägen Dreiecks fest – d.h., dass sich bei kleinem Viewport der Winkel verändert, ebenso beim border-Beispiel. Bei transform mit rotate() oder skew() bleibt der Winkel hingegen gleich.In manchen Fällen kann es aber ebenfalls sinnvoll sein, die Schräge aufzulösen. Das lässt sich gut mit Media Queries umsetzen. Was genau dann der notwendige Code ist, hängt davon ab, wie die Schräge erzeugt wurde. Beim header-Beispiel könnte man die Schräge bei kleinem Viewport mit maximal 30em folgendermaßen begradigen:
@media (max-width: 30em) {
header::after { height: 0; }
}
Soll hingegen das Element mit der 3rem Höhe beibehalten, aber gerade dargestellt werden, können Sie auf clip-path: none zurückgreifen.

Schatten:box-shadow (oben) im Unterschied zu filter (unten)(Bild 6)
Maurice
Wenn Sie eine Schräge über linear-gradient() oder border definiert haben und einen Schatten benötigen, so bringt box-shadow nicht den gewünschten Effekt. box-shadow zeichnet nämlich immer den Schatten um Boxen, also um die rechteckigen Formen. Wenn der Schatten hingegen der Schräge folgen soll, hilft die filter-Eigenschaft mit der drop-shadow()-Funktion (Bild 6):
filter: drop-shadow(0 0.50em 0.3em rgba(0, 0, 0, 0.5));
Eine weitere Besonderheit zeigt sich bei der Verwendung von clip-path in Kombination mit Schatten. Wenn Sie bei einem Element mit clip-path einen Schatten mit filter und der drop-shadow()-Funktion definieren, hat das keine Auswirkung. Der Schatten wird eben auch weggeschnitten. Die Lösung besteht darin, dass man den Filter beim Elternelement anwendet.Das waren Beispiele für mit CSS gezeichnete Schatten, für einen individuellen Schatten kann man sich mit Bildern behelfen.