Gut abgerundet: Zusammengesetzte Formen in CSS

Avatar of Parker Bennett
Parker Bennett am

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

Der folgende Beitrag ist ein Gastbeitrag von Parker Bennett. Parker ist hier ein kleiner Stammgast, bekannt dafür, häufige Probleme mit einzigartigen Lösungen anzugehen. Diesmal ist er wieder dabei, komplexe Formen mit Hintergrundbildern, Schatten und Kurven zu erstellen, die dennoch flexibel sind.

Ich liebe es, an Designprojekten mitzuarbeiten, weil es mich oft dazu bringt, neue Dinge auszuprobieren. Kürzlich erhielt ich ein Design-Comp, das etwa so aussah: eine abgerundete, zusammengesetzte Form als fester Header mit einer texturierten Vertiefung, die rundherum einen inneren Schatten hatte (ein „Becken“). Nun, dachte ich, wie schwer kann das schon sein?

Kurvig!

Eine Antwort war natürlich super einfach: Ich hätte mich entscheiden können, ein Bild zu zerlegen und transparente .png-Dateien für das kurvige untere Ende – Schatten und alles – mit einer „Endkappe“ zu verwenden, die es der rechten Hälfte erlauben würde, sich responsiv zu skalieren (die erste Spalte war als feste Breite konzipiert).

Aber ich wollte mehr Flexibilität für die Zukunft und entschied mich daher, es mit CSS zu lösen. Hier ist der Ansatz, den ich schließlich wählte. Nichts Spektakuläres, nur gutes altes CSS.

CodePen ist sassy!

CodePen erwies sich als unverzichtbar für all meine Experimente und auch für die Kundenrezension. Ein großer Vorteil war die Möglichkeit, in SCSS zu schreiben und schnell das Ergebnis zu sehen: Ich konnte verschiedene Breiten, Farben, Schatten, Eckradien usw. ausprobieren, indem ich einfach Variablen änderte.

Ich verwendete Variablen für bestimmte Höhen und Breiten sowie für die Größen von box-shadow und border-radius und nutzte diese dann, um zusätzliche Größen zu berechnen – unter Verwendung von Verhältnissen, wo es sinnvoll war, Elemente des Designs miteinander zu verbinden.

Variablen rocken!

In einer Fixierung

Für die meisten Projekte verwende ich ein zentriertes .page-wrap, das einen Prozentsatz des Browserfensters ausmacht. Aber wenn Sie Ihren Header mit position: fixed oben anheften, ist er nicht mehr vom page-wrap umschlossen. Eine Lösung besteht darin, mit dem page-wrap *nach* dem fixierten Header zu beginnen und einen header-wrap einzuschließen, der die Breite, die Ränder und den Abstand des page-wraps dupliziert (Details in diesem CodePen).

Um die Illusion aufrechtzuerhalten, dass der scrollende Inhalt in einem „ausgeschnittenen“ Bereich darunter liegt, verwendete ich overflow: hidden, um den Schatten des Headers an den Seiten abzuschneiden. Dies erforderte ein zweites Wrapper-div, um auch einen kleinen Abstand zwischen dem Inhalt und dem Fensterrahmen bei kleinen Breiten aufrechtzuerhalten (ja, ich bin einfach so penibel).

z-index: Leveling Up

Natürlich wollte ich die Markup schlank halten und mich nicht auf die Quellreihenfolge für das Layout verlassen. Ich habe Pseudo-Elemente verwendet, wo sie sinnvoll erschienen, und mich stark auf absolute Positionierung verlassen, um Dinge an ihren Platz zu bringen – wobei ich z-index verwendet habe, um zu ändern, wie sie sich überlappen. Da die absolute Positionierung das Element aus dem Layoutfluss entfernt, müsste ich manchmal kompensieren, z. B. padding zu anderen Elementen hinzufügen, um diesen Raum zu füllen.

Während ich die Positionierung ausarbeitete, stellte ich fest, dass ich mich dank der Eigenheiten der Stapelreihenfolge in eine z-index-Ecke malen konnte: z-index erfordert Positionierung, um zu funktionieren, unpositionierte Elemente werden zuerst gerendert, und es ist leicht, den Überblick zu verlieren, welche Elemente durch den „Stapelkontext“ eingeschränkt sind – zum Beispiel können Pseudo-Elemente nicht über den z-index ihres übergeordneten Elements hinausgehen (siehe Demo auf CodePen).

Ich habe auch den z-index von Schatten geändert und sie zu einem separaten Pseudo-Element gemacht. Dies ermöglichte es mir, Schatten hinter Objekte zu schieben, wo sie verdeckt werden mussten, oder, wie an den Seiten des scrollenden .main-Inhalts, sie anzuheben, um alles zu bedecken, was den Rand erreichte, damit die Illusion von Tiefe nicht gebrochen wurde.

/* elements that reach the edges of .main need to fall
   under edge shadow to maintain "cut-out" illusion */

.well-sides {
  /* child elements absolute */
  position: relative;
  overflow: hidden; }

.well-sides:before, .well-sides:after {
  content: "";
  display: block;
  position: absolute;
  /* higher than any z-index in .main, lower than header */
  z-index: 99;
  /* shadow size */
  top: -20px;
  height: 120%;
  /* shadow size */
  width: 20px;
  background: transparent; }

.well-sides:before {
  left: 0;
  /* negative spread */
  -webkit-box-shadow: inset 20px -20px 20px -20px rgba(0,0,0,0.35);
     -moz-box-shadow: inset 20px -20px 20px -20px rgba(0,0,0,0.35);
          box-shadow: inset 20px -20px 20px -20px rgba(0,0,0,0.35); }

.well-sides:after {
  right: 0;
  /* negative spread */
  -webkit-box-shadow: inset -20px 20px 20px -20px rgba(0,0,0,0.35);
     -moz-box-shadow: inset -20px 20px 20px -20px rgba(0,0,0,0.35);
          box-shadow: inset -20px 20px 20px -20px rgba(0,0,0,0.35); }

Ecken abschneiden

Leider gibt es in CSS keine praktische Möglichkeit, ein Objekt mit einer konkaven Rundung zu erstellen. Wo die beiden abgerundeten Rechtecke aufeinandertrafen, verwendete ich einen „Patch“, um die Naht des inset box-shadow zu überdecken und den texturierten Hintergrund in den Bereich der inneren Ecke zu erweitern. Dann überlagerte ich ihn mit einer abgerundeten weißen Ecke und schuf so den Negativraum als Positiv. Schließlich fügte ich der abgerundeten Ecke einen normalen box-shadow hinzu (abgeschnitten durch overflow: hidden), um sie mit dem inset box-shadow zu verschmelzen.

Der erhabene Schatten im „Patch“ musste etwas „opak gemacht“ werden, um zum erhabenen Schatten zu passen.
Der innere Kreis

Für die anderen inneren Kurven positionierte ich ein transparentes Quadrat mit einer abgerundeten Ecke und einem dicken weißen Rand auf beiden Seiten, um die Illusion zu vervollständigen. Ich verwendete die Größen von border-radius und box-shadow als Variablen, um die Größe und Platzierung der Ecken zu bestimmen.

Wie alles gestapelt ist

Hier ist, wie ich die Teile zusammengesetzt habe

Diashow hier. Wenn Sie über Syndizierung lesen, sehen Sie den echten Blogbeitrag, um die Diashow zu sehen.

<
>

  • Zusammenfassend

    Es stimmt, dass ich eine gute Herausforderung mag, aber die Ausarbeitung auf diese Weise gab mir auch viel Flexibilität während des Prozesses und einen Vorsprung bei einem mobil-responsiven Layout (das kurvige untere Ende bei kleineren Größen gerade machen, das Menü kürzen usw.). Auf jeden Fall hoffe ich, dass Sie einige nützliche Einblicke in meine viel zu gründliche Erkundung gefunden haben. Wenn Sie Fragen, Kommentare oder Korrekturen haben, melden Sie sich bei mir: parker@parkerbennett.com.