Grundformen & Pfad… Werden sie sich nie treffen?

Avatar of Chris Coyier
Chris Coyier am

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

Es gibt einige Werte in CSS, die das Zeichnen von Formen ermöglichen. Zum Beispiel gibt es die Funktion circle(), die ein gültiger Wert für einige CSS-Eigenschaften ist. „Zeichnen“ ist vielleicht nicht das richtige Wort. Es ist nicht so wie in SVG, wo man ein <circle>-Element erstellen kann und es buchstäblich einen Kreis zeichnet.

Diese Formen in CSS sind für andere Dinge gedacht. Nämlich: clip-path, das für das Erstellen von Clipping-Masken verwendet wird, und shape-outside, um Text um Formen fließen zu lassen.

Es gibt einige andere CSS-Eigenschaften, die SVG-ähnliche Formen verwenden, um ihre Funktionalität zu erfüllen. Zum Beispiel ist offset-path Teil der Animation von Elementen entlang von Vektorpfaden unter Verwendung der Funktion path(). Pfade sind fantastisch. Sie sind das ultimative Zeichenelement, da sie alles zeichnen können, und alle anderen Formen sind im Wesentlichen syntaktischer Zucker für Pfade.

Was sind die Grundformen?

Es gibt vier Grundformen

  • polygon()
  • circle()
  • ellipse()
  • inset()

Was sind Pfade?

Pfade stammen aus SVG. Sie haben eine spezielle Syntax, die es ihnen ermöglicht, alles zu zeichnen.

<path d="M 25,100 C 25,150 75,150 75,100 S 100,25 150,75" />
path("M 25,100 C 25,150 75,150 75,100 S 100,25 150,75");

Hier wird es irgendwie seltsam

  • Die Eigenschaften clip-path und shape-outside können alle „Grundformen“ wie circle() und polygon() aufnehmen, aber nicht path().
  • Die Eigenschaft offset-path kann path() aufnehmen, aber nicht die „Grundformen“.
  • Sie können auch das d-Attribut eines <path> über CSS steuern, aber nicht die Attribute vieler anderer SVG-Elemente.

Ich bin mir nicht wirklich sicher, warum das so ist, und ich bin sicher, dass sich die Dinge mit der Zeit ändern werden, aber es ist gut, es zu wissen.

Lassen Sie uns das ausführen.

clip-path erlaubt Grundformen (aber nicht path())

Nehmen wir an, Sie möchten quadratische Avatare in Polygone ausschneiden, für ein lustiges Design. Das können Sie! Das Bild könnte ein HTML-Element sein wie

<img src="avatar.jpg" alt="User Avatar" class="avatar">
.avatar {
  clip-path: polygon(0% 5%, 100% 0%, 100% 85%, 65% 80%, 75% 100%, 40% 80%, 0% 75%);
}

Siehe den Pen Clipped Avatars von Chris Coyier (@chriscoyier) auf CodePen.

Aber sagen wir, Sie möchten den Avatar so ausschneiden:

Nun, das können Sie nicht. Zumindest nicht direkt in CSS. Diese Kurven erfordern einen path, und clip-path kann keine path. Glücklicherweise akzeptiert clip-path eine url(), die die ID eines <clipPath>-Elements akzeptiert.

Siehe den Pen Clipped Avatars von Chris Coyier (@chriscoyier) auf CodePen.

offset-path erlaubt Pfade (aber nicht Grundformen)

Sagen wir, wir wollen ein Objekt entlang der Außenseite der gerade verwendeten Sprechblasengeformten Form bewegen. Die Eigenschaft offset-path ist genau dafür gedacht.

<div class="move-me"></div>
.move-me {
  offset-path: path("M100.5,39.47C100.5,58.3,83.36,74,60.58,77.64l16.85,19.9L33.94,76.25C14.47,70.92.5,56.47.5,39.47c0-21.52,22.39-39,50-39S100.5,17.95,100.5,39.47Z");
  animation: move 3s linear infinite;
}
@keyframes move {
  100% { motion-offset: 100%;}
}

Siehe den Pen offset-path on path von Chris Coyier (@chriscoyier) auf CodePen.

Aber was ist, wenn Sie das Element in einem Kreis bewegen möchten? Die Grundformen-Version eines Kreises hat eine super einfache Syntax, wie circle(50% at 50% 50%); Aber leider werden die Grundformen nicht unterstützt. Der Standard erlaubt sie, aber sie funktionieren nicht. Es ist irgendwie verständlich, denn… wie würde man die Richtung der Bewegung definieren?

Sie können sich immer noch in einem Kreis bewegen, denn der allmächtige Pfad kann einen Kreis zeichnen, wie

.move-me {
  /* a circle */
  offset-path: path("M100,50a50,50,0,1,1-50-50A50,50,0,0,1,100,50Z");
  animation: move 3s linear infinite;
}
@keyframes move {
  100% { motion-offset: 100%;}
}

Und diese Befehle geben natürlich eine Richtung vor. Es gibt auch andere Möglichkeiten, sich in einem Kreis zu bewegen.

shape-outside erlaubt Grundformen (aber nicht path())

Sagen Sie, Sie möchten Text um eine Eiform wickeln, weil, ich weiß nicht, Sie haben Text von Alice geschrieben, die mit Humpty Dumpty spricht. Die Eiform ist eine gute Ausrede, um die Grundform ellipse() zu verwenden.

<div class="page-wrap">
  <div class="egg"></div>
  <p>"I don't know what you mean by 'glory,'" Alice said.</p>
  <p>Humpty Dumpty smiled contemptuously. "Of course you don't—till I tell you. I meant 'there's a nice knock-down argument for you!'"</p>

 ...
.egg {
  float: left;
  shape-outside: ellipse(120px 160px at 50% 50%);
  width: 280px;
  height: 320px;
}

Wir würden wahrscheinlich ein identisches clip-path (um tatsächlich die Eiform zu erzeugen) einstellen und es einfärben.

Siehe den Pen Shape Outside Egg von Chris Coyier (@chriscoyier) auf CodePen.

Aber was ist, wenn Sie Text um eine *kurvige* Form wickeln möchten, wie hier in Illustrator gezeigt?

Textumfluss in Adobe Illustrator

Leider akzeptiert shape-outside kein path(), also können Sie das nicht. Aber irgendwie schon. Es akzeptiert url(), über die Sie auf ein Bild verlinken können (es muss nicht einmal SVG sein, aber SVG macht Sinn). Das Bild kann einen schönen kurvigen Pfad haben, wie wir es anstreben.

Siehe den Pen Wrap Text Around Curve von Chris Coyier (@chriscoyier) auf CodePen.

Die url() kann sogar eine Daten-URL sein. Beachten Sie auch, dass jedes Element, das shape-outside verwendet, gefloated sein muss, eine Einschränkung, die möglicherweise mit CSS Exclusions behoben wird.

<path> nimmt path() auf

Hier ist eine, die logisch beginnt. Sagen Sie, Sie haben einen Pfad

<svg>
 <path d=" ... " />
</svg>

Sie können die Form dieses Pfades über CSS ändern, z. B. bei einem Hover

svg:hover path {
  d: path(" ... ");
}

Siehe den Pen Change path on hover von Chris Coyier (@chriscoyier) auf CodePen.

Sie können die Form sogar überblenden lassen, wenn die Pfaddaten zufällig die gleiche Anzahl von Punkten haben.

Es wird jedoch etwas verwirrend. Nehmen Sie an, Sie haben stattdessen ein <polygon>.

<svg>
 <polygon points=" ... " />
</svg>

Wie aktualisieren Sie es mit CSS?

polygon {
  /* Nope */
  points: " ... ";

  /* Nope */
  points: points(" ... ");

  /* Nope */
  points: polygon(" ... ");
}

Soweit ich weiß, gibt es keine Möglichkeit. Was seltsam erscheint, da Polygon ansonsten überall unterstützt wird. Ich stelle mir vor, ein Teil des Problems ist, dass die Funktion polygon() anders ist als das Attribut points. Die Funktion polygon() nimmt Prozentsätze und Zahlen mit *Einheiten* in CSS, während das Attribut points *einheitenlose* Zahlen nimmt (wie alles in SVG). Es sind unterschiedliche Bestien, und diese Überlappung ist umständlich.

Es ist auch nicht so, dass SVG-Formen, die sich mit Grundformen überschneiden, nicht verändert werden können. Alle Attribute eines <circle> können beispielsweise mit CSS geändert werden.

svg:hover circle {
  cx: 40;
  cy: 40;
  r: 40;
}

Siehe den Pen Altering Circle Attributes von Chris Coyier (@chriscoyier) auf CodePen.

Langfassung: Es gibt normalerweise einen Weg, das zu erreichen, was Sie erreichen wollen, aber es ist verwirrend, was wo unterstützt wird/nicht.