Navigation überspringen

CSS: clip-path mit border und border-radius? Mit diesen Work­arounds klappt’s!

26.3.2022·Kommentare:  0Retweets:  1 2

Mein letztes großes Redesign ist zwar schon lange her, nichtsdestotrotz habe ich seitdem ständig an Details meines Blogs gefeilt. Eines davon waren die Blätterbuttons am Ende jedes Posts, mit denen man zum nächsten oder vorherigen Post gelangen konnte. Diese habe ich nun mittels clip-path neu gestaltet und mit zwei simplen Workarounds sowohl die border- als auch die border-radius-Eigenschaft nachgebaut. Wie das geht, erfahrt ihr in diesem Post.

Das Ziel: Blätterbuttons in Pfeilform

Der Einfachheit halber waren die Buttons simple, abgerundete Boxen – wirklich zufrieden war ich damit aber nie. Um die Blätterrichtung zu verdeutlichen, habe ich mittels content-Eigenschaft jeweils einen Pfeil nach links bzw. rechts an den Link-Titel angehängt. Als Button funktionierte das Konstrukt zwar irgendwie, aber elegant war es nicht besonders.

Mein Plan war, auf den Inline-Pfeil zu verzichten und dem Button selbst die Form eines Pfeils zu geben. Nur wie? Auf Bilder als grafische Hilfsmittel will ich hier einerseits verzichten und andererseits mussten die Blätterbuttons aufgrund der variablen Titellänge der Posts sowie des Responsive-Designs sowohl in der Höhe als auch in der Breite flexibel sein.

Der übliche Workaround, dem Button mit einem gedrehten Quadrat und entsprechend ausgeblendeten Borders eine Spitze zu verpassen, erwies sich als recht umständlich und zudem war der Übergang der Schenkel zum rechteckigen Teil des Buttons nie sauber.

Was ist clip-path?

Mangels Bedarf hatte ich mich bis dahin nie wirklich mit der clip-path-Eigenschaft in CSS auseinandergesetzt. Vereinfacht gesagt, kann man damit ein rechteckiges HTML-Element wie mit einer Schere zuschneiden.

clip-path ist ziemlich mächtig und kann weitaus mehr, als hier beschrieben. Der Einfachheit halber beschränke ich mich aber auf die Möglichkeit mittels clip-path: polygon und der Angabe beliebig vieler Koordinatenpunkte einen Pfad zum Ausschneiden zu definieren.

So kann man mit …

<a class="button" href="#">Label</a>
<style>
.button {
background:black;
clip-path: polygon(
0% 0%,
95% 0%,
100% 50%,
95% 100%,
0% 100%
);
}
</style>

… bereits einen simplen Button in Pfeilform realisieren (das komplette Code-Beispiel findet ihr am Ende verlinkt):

Label

Jeder Koordinatenpunkt, der in den üblichen CSS-Maßeinheiten (em, %, px etc.) angegeben werden kann, gibt dabei einen Wegpunkt für die Schnittlinie an. Die Richtung spielt dabei keine Rolle, beachten muss man nur, dass nach Angabe des letzten Koordinatenpunkts die Schnittlinie zum ersten Koordinatenpunkt gezogen wird.

In diesem Beispiel beginne ich links oben (0% 0%) und arbeite mich im Uhrzeigesinn durch. 100% 50% gibt dabei die Pfeilspitze außen rechts an (da die Ecken rechts bereits bei 95% enden, wird mit den 100% die Spitze nach außen gezogen).

Das Problem: Keine Rahmengestaltung möglich

Damit kann man prinzipiell alle möglichen Formen nachbilden, es gibt aber zwei Probleme:

  1. Man kann keine Border definieren
  2. Man kann keine »runden Ecken« (z.B. mittels border-radius) realisieren

Beides wollte ich für meine Blätterbuttons aber haben und habe dafür zwei taugliche Workarounds gefunden, die nicht nur – was sonst?! – standardkonform sind, sondern auch in allen gängigen Browsern unterstützt werden.

border mittels calc nachbauen

Punkt 1 ist der einfachere. Eine Border kann man nämlich realisieren, indem man die Form ein zweites Mal, nur eben eine Spur kleiner, über die erste Form legt.

Nur wie macht man diese zweite Form exakt um die gewünschte Rahmendicke kleiner? Indem man mittels calc die gewünschte Dicke abzieht (bzw. hinzuaddiert):

<a class="button" href="#"><span>Label</span></a>
<style>
.button, .button span {
display:block;
min-height:60px;
line-height:60px;
text-align:center;
}
.button {
background:black;
clip-path: polygon(
0% 0%,
95% 0%,
100% 50%,
95% 100%,
0% 100%
);
}
.button span {
background:white;
clip-path: polygon(
calc( 0% + 2px) calc(0% + 2px),
calc( 95% - 2px) calc(0% + 2px),
calc(100% - 3px) 50%,
calc( 95% - 2px) calc(100% - 2px),
calc( 0% + 2px) calc(100% - 2px)
);
}
</style>

Damit hat man nun eine zweite Form, die exakt um 2 Pixel kleiner ist:

Label

Man kann natürlich auch versuchen, nur mit einer Padding-Angabe bei .button durchzukommen, allerdings sieht dann die Spitze nicht mehr ganz so gut aus. Das ist übrigens auch der Grund, warum ich genau dort -3 statt -2 Pixel angegeben habe. Browser rendern aus irgendeinem Grund die Schenkel dann gleichmäßiger.

Abgerundete Ecken mit mehr Wegpunkten selber bauen

Punkt 2 ist nicht unbedingt komplexer, aber jedenfalls aufwändiger. Wenn man nämlich nicht gerade eine komplizierte Form mit dutzenden Ecken hat, die abgerundet werden sollen, kann man sich mit zusätzlichen Wegpunkten behelfen und die Kurve für die Rundung manuell beschreiben.

Ja, das ist etwas mühsam und sieht, wenn man wirklich ganz genau hinsieht, nicht gleich gut wie eine mit border-radius angegebene Rundung aus, aber eine praktikable Lösung ist es allemal:

<a class="button" href="#"><span>Label</span></a>
<style>
.button, .button span {
display:block;
min-height:60px;
line-height:60px;
text-align:center;
}
.button {
background:black;
clip-path: polygon(
calc( 0% + 0px) calc( 0% + 8px),
calc( 0% + 1px) calc( 0% + 5px),
calc( 0% + 2px) calc( 0% + 3px),
calc( 0% + 3px) calc( 0% + 2px),
calc( 0% + 3px) calc( 0% + 2px),
calc( 0% + 5px) calc( 0% + 1px),
calc( 0% + 8px) calc( 0% + 0px),
95% 0,
100% 50%,
95% 100%,
calc( 0% + 8px) calc(100% - 0px),
calc( 0% + 5px) calc(100% - 1px),
calc( 0% + 3px) calc(100% - 2px),
calc( 0% + 3px) calc(100% - 2px),
calc( 0% + 2px) calc(100% - 3px),
calc( 0% + 1px) calc(100% - 5px),
calc( 0% + 0px) calc(100% - 8px)
);
}
.button span {
background:white;
clip-path: polygon(
calc( 0% + 0px + 2px) calc( 0% + 8px + 2px),
calc( 0% + 1px + 2px) calc( 0% + 5px + 2px),
calc( 0% + 2px + 2px) calc( 0% + 3px + 2px),
calc( 0% + 3px + 2px) calc( 0% + 2px + 2px),
calc( 0% + 3px + 2px) calc( 0% + 2px + 2px),
calc( 0% + 5px + 2px) calc( 0% + 1px + 2px),
calc( 0% + 8px + 2px) calc( 0% + 0px + 2px),
calc( 95% - 2px) calc( 0% + 2px),
calc(100% - 3px) 50%,
calc( 95% - 2px) calc(100% - 2px),
calc( 0% + 2px) calc(100% - 2px),
calc( 0% + 8px + 2px) calc(100% - 0px - 2px),
calc( 0% + 5px + 2px) calc(100% - 1px - 2px),
calc( 0% + 3px + 2px) calc(100% - 2px - 2px),
calc( 0% + 3px + 2px) calc(100% - 2px - 2px),
calc( 0% + 2px + 2px) calc(100% - 3px - 2px),
calc( 0% + 1px + 2px) calc(100% - 5px - 2px),
calc( 0% + 0px + 2px) calc(100% - 8px - 2px)
);
}
</style>

Fertig sieht der Button wie folgt aus:

Label

Das Code-Beispiel könnt ihr euch auch im Browser ansehen.

Eure Meinung

Was meint ihr? Ist das eine alltagstaugliche Lösung für einen Blätterbutton mit Pfeilform, habt ihr Fragen oder gar Verbesserungsvorschläge? Darauf freue ich mich wie immer in den Kommentaren!


Neueste Artikel

Schlagwörter

· · · ·


Kommentieren

Am liebsten hier, gerne aber auch auf Twitter und Facebook.
Ich freue mich über jeden Kommentar und antworte gern innerhalb von 24 Stunden.