Schicke CSS-Rahmen mit Masken (Zickzack, wellig und mehr)

Avatar of Temani Afif
Temani Afif am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Haben Sie jemals versucht, CSS-Rahmen in einem sich wiederholenden Zickzackmuster zu erstellen? So wie dort, wo ein farbiger Abschnitt einer Website endet und ein andersfarbiger Abschnitt beginnt – nicht mit einer geraden Linie, sondern mit schrägen Zickzacklinien, abgerundeten Höckern oder Wellen. Es gibt eine Reihe von Möglichkeiten, wie Sie diese Art von CSS-Rahmen erstellen könnten, die bis zur Verwendung eines background-image zurückreichen. Aber wir können moderner und programmatischer vorgehen. In diesem Artikel werden wir einige moderne CSS-Maskierungstechniken untersuchen, um diesen Look zu erzielen.

Bevor wir uns jedoch mit den technischen Details befassen, werfen wir einen Blick darauf, was wir erstellen. Ich habe einen CSS-Rahmengenerator erstellt, mit dem Sie in wenigen Sekunden jede Art von Rahmen einfach generieren und den CSS-Code erhalten können.

Haben Sie das gesehen? Mit der CSS-mask-Eigenschaft und einigen CSS-Verläufen erhalten wir einen responsiven und cool aussehenden Rahmen – alles allein mit CSS. Nicht nur das, sondern ein solcher Effekt kann auf jedes Element angewendet werden, bei dem wir jede Art von Farbgebung haben können (z. B. Bild, Verlauf usw.). Wir erhalten all dies ohne zusätzliche Elemente, Pseudoelemente oder magische Zahlen, die aus dem Nichts kommen!

Oh toll! Alles, was ich tun muss, ist, Code zu kopieren/einzufügen und fertig!

Stimmt, aber es ist gut, die Logik zu verstehen, um den Code bei Bedarf manuell anpassen zu können.

Dinge maskieren

Da alle unsere Effekte von der CSS-mask-Eigenschaft abhängen, lassen Sie uns kurz auffrischen, wie sie funktioniert. Direkt aus dem Standard

Der Effekt der Anwendung einer Maske auf ein grafisches Objekt ist so, als ob das grafische Objekt durch eine Maske auf den Hintergrund gemalt würde, wodurch Teile des grafischen Objekts vollständig oder teilweise maskiert werden.

Wenn wir die formale Syntax der mask-Eigenschaft überprüfen, sehen wir, dass sie einen <image> als Wert akzeptiert, was entweder eine URL eines Bildes oder einen Farbverlauf bedeutet. Verläufe sind das, was wir hier verwenden werden. Beginnen wir mit einfachen Beispielen

Im ersten Beispiel dieser Demo wird ein Verlauf verwendet, um den Eindruck zu erwecken, dass das Bild verblasst. Im zweiten Beispiel wird ebenfalls ein Verlauf verwendet, aber anstelle eines weichen Übergangs zwischen Farben wird ein harter Farbstopp verwendet, um die Hälfte des Bildes zu verbergen (oder zu maskieren). Dieses zweite Beispiel veranschaulicht die Technik, die wir zur Erstellung unserer schicken Rahmen verwenden werden.

Ach ja, und die CSS-mask-Eigenschaft kann mehrere Verläufe annehmen, solange sie durch Kommas getrennt sind. Das bedeutet, wir haben noch mehr Kontrolle, um zusätzliche Teile des Bildes zu maskieren.

Dieses Beispiel mit mehreren Maskierungsverläufen mag auf den ersten Blick etwas knifflig aussehen, aber was passiert, ist dasselbe wie beim Anwenden mehrerer Verläufe auf die background-Eigenschaft. Aber anstatt eine Farbe zu verwenden, die sich mit dem Seitenhintergrund vermischt, verwenden wir einen "transparenten" Schwarzton (#0000) für die verborgenen Teile des Bildes und volles Schwarz (#000) für die sichtbaren Teile.

Das war's! Jetzt können wir uns unseren schicken Rahmen widmen.

Zickzack-CSS-Rahmen

Wie wir im Video zu Beginn dieses Artikels gesehen haben, kann der Generator Rahmen an einer Seite, zwei Seiten oder allen Seiten anbringen. Beginnen wir mit der Unterseite und einer schrittweisen Illustration

  1. Wir beginnen mit dem Hinzufügen eines conic-gradient() mit einer bestimmten Abmessung in der Mitte.
  2. Als Nächstes wiederholen wir diesen Verlauf (indem wir no-repeat entfernen) und wir sehen bereits die Zickzackform!
  3. Verläufe sind dafür bekannt, Kantenglättungsprobleme zu haben, die zackige Kanten erzeugen (besonders in Chrome). Um dies zu vermeiden, fügen wir einen leichten Übergang zwischen den Farben hinzu und ändern blue 90deg, green 0 zu green, blue 1deg 89deg, green 90deg.
  4. Zuletzt verwenden wir alles innerhalb der mask-Eigenschaft!

Aus diesen Schritten können wir zwei Variablen extrahieren, um unsere Form zu definieren: Größe (40px) und Winkel (90deg). Hier ist, wie wir das mit Platzhaltern für diese Variablen ausdrücken können. Ich werde JavaScript verwenden, um diese Variablen durch ihre endgültigen Werte zu ersetzen.

mask:
  conic-gradient(
    from {-angle/2} at bottom,
    #0000, #000 1deg {angle - 1} ,#0000 {angle}
  ) 50%/{2*size*tan(angle/2)} 100%;

Wir können CSS-Benutzerdefinierte Eigenschaften für die Größe und den Winkel verwenden, aber trigonometrische Funktionen werden derzeit nicht unterstützt. In Zukunft werden wir etwas wie folgt tun können

--size: 40px;
--angle: 90deg;
mask:
  conic-gradient(
    from calc(var(--angle)/-2) at bottom,
    #0000, #000 1deg calc(var(--angle) - 1deg), #0000 var(--angle)
  ) 50%/calc(2*var(--size)*tan(var(--angle)/2)) 100%;

Ähnlich wie beim unteren Rahmen hat der obere fast den gleichen Code mit wenigen Anpassungen

mask:
  conic-gradient(
    from {180deg - angle/2} at top,
    #0000, #000 1deg {angle - 1}, #0000 {angle}
  ) 50%/{2*size*tan(angle/2)} 100%;

Wir haben bottom durch top ersetzt und dann die Drehung des Verlaufs auf 180deg - angle/2 anstelle von -angle/2 aktualisiert. So einfach ist das!

Das ist das Muster, das wir für die restlichen Seiten verwenden können, wie die linke Seite

mask:
  conic-gradient(
    from {90deg - angle/2} at left,
    #0000, #000 1deg {angle - 1}, #0000 {angle}
  ) 50%/100% {2*size*tan(angle/2)};

…und die rechte Seite

mask:
  conic-gradient(
    from {-90deg - angle/2} at right,
    #0000, #000 1deg {angle - 1}, #0000 {angle}
  ) 50%/100% {2*size*tan(angle/2)};

Lassen Sie uns die Rahmen für die Fälle erstellen, in denen sie auf zwei Seiten gleichzeitig angewendet werden. Wir können den gleichen Code wiederverwenden. Um sowohl den oberen als auch den unteren Rahmen zu erhalten, kombinieren wir einfach den Code des oberen und unteren Rahmens.

mask:
  conic-gradient(
    from {-angle/2} at bottom,
    #0000, #000 1deg {angle - 1}, #0000 {angle}
  ) bottom/{2*size*tan(angle/2)} 51% repeat-x;
  conic-gradient(
    from {180deg - angle/2} at top, 
    #0000, #000 1deg {angle - 1}, #0000 {angle}
  ) top   /{2*size*tan(angle/2)} 51% repeat-x;

Dasselbe gilt, wenn Rahmen auf die linke und rechte Seite gleichzeitig angewendet werden

mask:
  conic-gradient(
    from {90deg - angle/2} at left,
    #0000, #000 1deg {angle - 1}, #0000 {angle}
  ) left /51% {2*size*tan(angle/2)} repeat-y,
  conic-gradient(
    from {-90deg - angle/2} at right,
    #0000, #000 1deg {angle - 1}, #0000 {angle}
  ) right/51% {2*size*tan(angle/2)} repeat-y;

Wenn wir also Rahmen auf alle Seiten gleichzeitig anwenden wollen, addieren wir alle Verläufe zusammen, richtig?

Genau! Wir haben vier konische Verläufe (einen auf jeder Seite) und einen linear-gradient() in der Mitte. Wir setzen einen festen Winkel von 90deg, da dies der einzige ist, der zu schöneren Ecken ohne seltsames Überlappen führt. Beachten Sie, dass ich auch space anstelle von repeat-x oder repeat-y verwende, um schlechte Ergebnisse an Ecken wie dieser zu vermeiden

Größenänderung eines Containers mit Vier-Seiten-Konfiguration

Ausgestochene CSS-Rahmen

Nun widmen wir uns den ausgestochenen Rahmen!

Oh nein! Noch eine lange Erklärung mit viel Berechnung?!

Überhaupt nicht! Es gibt hier nichts zu erklären. Wir nehmen alles aus dem Zickzack-Beispiel und aktualisieren das conic-gradient() mit einem radial-gradient(). Es ist sogar noch einfacher, weil wir keine Winkel handhaben müssen – nur die Grössenvariable.

Hier ist eine Illustration für eine Seite, um zu sehen, wie wenig wir tun müssen, um vom Zickzack-Rahmen zum ausgestochenen Rahmen zu wechseln

Wieder habe ich alles, was ich dort getan habe, war, das conic-gradient() durch dieses zu ersetzen (mit Platzhaltern für die Größe)

mask: radial-gradient({size} at bottom,#0000 98%,#000) 50% / {1.85*size} 100%;

Was steckt hinter den magischen Zahlen 1,85 und 98 %?

Logischerweise sollten wir 100 % anstelle von 98 % verwenden, um einen Kreis zu erhalten, der die Ränder des Hintergrundbereichs berührt. Aber wieder ist es das Kantenglättungsproblem und diese zackigen Kanten. Wir verwenden einen etwas kleineren Wert, um seltsames Überlappen zu verhindern.

Der Wert 1,85 ist eher eine persönliche Präferenz als etwas anderes. Ich habe anfangs 2 verwendet, was der logische Wert für einen perfekten Kreis ist, aber das Ergebnis sieht nicht ganz so gut aus, daher schafft der kleinere Wert eine nahtlosere Überlappung zwischen den Kreisen.

Hier ist der Unterschied

Nun müssen wir dies für die restlichen Seiten wiederholen, genau wie wir es beim Zickzack-CSS-Rahmen getan haben, und wissen Sie was? Wir brauchen auch einen Verlauf selbst für den Fall, dass wir die Ober-/Unter- oder Links-/Rechts-Version wollen.

Der einzige Fall, in dem wir mehr als einen Verlauf benötigen, ist die Konfiguration für alle Seiten. Ähnlich wie beim Zickzack-Rahmen müssen wir vier radiale Verläufe und einen linearen Verlauf verwenden, aber ich musste die CSS-clip-path-Eigenschaft einführen, um ein Überlappungsproblem an den Ecken zu beheben. Sie können den Unterschied zwischen mit und ohne clip-path im folgenden Demo sehen

Es ist ein Acht-Punkte-Pfad, um die Ecken zuzuschneiden

clip-path: polygon(
   {2*size} 0,calc(100% - {2*size}) 0,
   100% {2*size},100% calc(100% - {2*size}),
   calc(100% - {2*size}) 100%,{2*size} 100%,
   0 calc(100% - {2*size}),0 {2*size}
);

Kammmuschelförmige CSS-Rahmen

Für diesen Rahmen benötigen wir immer zwei Verläufe, unabhängig von der Seitenkonfiguration. Wir verwenden einen radialen Verlauf, um ein wiederholtes Muster von Kreisen zu erstellen, und einen linearen Verlauf, um sie abzudecken und nur die gewünschten Seiten anzuzeigen.

Hier ist ein Demo, um einige der Fälle zu veranschaulichen

Beachten Sie, wie ich die Werte round und space verwende. Das dient dazu, sicherzustellen, dass wir keine Kreise abschneiden und uns nicht auf weitere Verläufe verlassen müssen. Und wieder ist dieser Wert 1,85 ein Wert, der einer persönlichen Präferenz entspricht.

Wellig CSS-Rahmen

Der wellige Rahmen ist eine Art Kombination der beiden vorherigen Rahmen. Hier ist eine Illustration, um zu verstehen, wie wir die untere Welle aufbauen.

Wir wiederholen diese Form unten und sind fertig.

mask: 
  radial-gradient({size} at 75% 100%,#0000 98%,#000) 50% calc(100% - {size})/{4*size} 100% repeat-x,
  radial-gradient({size} at 25% 50% ,#000 99%,#0000 101%) bottom/{4*size} {2*size} repeat-x;

Wir machen denselben Prozess für die anderen Seiten wie bei den Zickzack- und abgerundeten CSS-Rahmen. Alles, was wir brauchen, ist, ein paar Variablen zu aktualisieren, um für jede Seite eine andere Welle zu haben.

Teile des CSS für jede Seite werden angezeigt. Der vollständige Code ist im Generator zu finden.

Wie wäre es, einen welligen CSS-Rahmen an allen vier Seiten anzubringen? Haben wir dann insgesamt 8 Verläufe??”

Nein, und das liegt daran, dass es keine Demo gibt, bei der ein welliger Rahmen an allen vier Seiten angebracht ist. Ich konnte keine Kombination von Verläufen finden, die an den Ecken ein gutes Ergebnis liefert. Vielleicht weiß jemand, der das liest, einen guten Ansatz? 😉

Was wir hier gemacht haben, ist ein einfacher Fall eines welligen Rahmens. Ich habe einen weiteren Artikel, in dem ich detailliert auf die Erstellung komplexer welliger Formen eingehe.

Das ist grenzwertig großartig!

Nun kennen Sie die Details von meinem coolen kleinen Online-CSS-Rahmengenerator! Sicher, Sie können den Code verwenden, den er ausgibt, und es funktioniert gut – aber jetzt kennen Sie das geheime Rezept, das ihn zum Laufen bringt.

Insbesondere haben wir gesehen, wie Verläufe verwendet werden können, um Teile eines Elements zu maskieren. Dann haben wir uns mit *mehreren* Verläufen beschäftigt, um bestimmte Formen aus diesen Gradienten-CSS-Masken zu erstellen. Und das Ergebnis ist ein Muster, das entlang der Kanten eines Elements verwendet werden kann, wodurch die Illusion von schicken Rahmen entsteht, für die Sie sonst auf background-image zurückgreifen würden. Nur auf diese Weise reicht es aus, einige Werte auszutauschen, um das Erscheinungsbild zu ändern, anstatt eine ganze Rasterbilddatei oder etwas Ähnliches zu ersetzen.