Skip to content

Commit

Permalink
[css-shapes-2] Add a detailed example for shape() (#11548)
Browse files Browse the repository at this point in the history
* [css-shapes-2] Add detailed example for

* Add SVGs

* Remove animation bit
  • Loading branch information
noamr authored Jan 21, 2025
1 parent 8e1b503 commit 3492c4a
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 0 deletions.
114 changes: 114 additions & 0 deletions css-shapes-2/Overview.bs
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,120 @@ The ''shape()'' Function</h4>
which affects how line-joins and line-caps are rendered.
</dl>

<h5 id=shape-examples>Using ''shape()'' to create responsive, parametric speech bubble</h5>

<div class=example>
The ''shape()'' function enables shapes that are responsive, rather than scalable.
While the ''polygon()'' shape is also responsive, it doesn't support curves.

To demonstrate, let's start with a speech bubble, such as the following:

<img src="images/bubble.svg" width=300 style="background: unset">

Using this shape with a ''clip-path'' can be done by using the ''path()'' function:

<pre highlight="css">
.bubble { clip-path: path("m 5 0 H 95 Q 100 0 100 5 V 92 Q 100 97 95 97 H 70 l -2 3 l -2 -3 H 5 Q 0 97 0 92 V 5 Q 0 0 5 0") };
</pre>

Altohugh this path can easily scale, the scaled results are not always desirable. e.g. when scaled to a small balloon, the arrow and corners are scaled to become almost invisible:

<img src="images/bubble.svg" width=100 style="background: unset">

To construct this shape using the ''shape()'' function, let's start by turning all the pixel values from the ''path'' function to percentages.
Note that the ''shape()'' function begins with <css>from</css>:

<pre highlight="css">
.bubble { clip-path: shape( from 5% 0%,
hline to 95%,
curve to 100% 5% with 100% 0%,
vline to 92%,
curve to 95% 97% with 100% 97%,
hline to 70%,
line by -2% 3%,
line by -2% -3%,
hline to 5%,
curve to 0% 92% with 0% 97%,
vline to 5%,
curve to 5% 0% with 0% 0%); }
</pre>

To make this path responsive, as in, respond well to size changes, we will convert some of its units to ''px'' values,
specifically the ones the control the curves and arrows:

<pre highlight="css">
.bubble { clip-path: shape( from 5px 0%,
hline to calc(100% - 5px),
curve to 100% 5px with 100% 0%,
vline to calc(100% - 8px),
curve to calc(100% - 5px) calc(100% - 3px) with 100% calc(100% - 3px),
hline to 70%,
line by -2px 3px,
line by -2px -3px,
hline to 5px,
curve to 0% calc(100% - 8px) with 0% calc(100% - 3px),
vline to 5px,
curve to 5px 0% with 0% 0%); }
</pre>

When applied as ''clip-path'', it would looks like the following:
<p>
<img src="images/bubble-50.svg" width=150 style="background: unset">
</p>

The whole speech bubble is scaled to the reference box, while the curves and arrows stay more constant.

Since ''shape()'' uses CSS units, we can replace some of the edges with ''position'' values:

<pre highlight="css">
.bubble { clip-path: shape(from 5px 0,
hline to calc(100% - 5px),
curve to right 5px with right top,
vline to calc(100% - 8px),
curve to calc(100% - 5px) calc(100% - 3px) with right calc(100% - 3px),
hline to 70%,
line by -2px 3px,
line by -2px -3px,
hline to 5px,
curve to left calc(100% - 8px) with left calc(100% - 3px),
vline to 5px,
curve to 5px top with left top); }
</pre>

Another useful feature of ''shape()'' is that it can be used alongside CSS properties. In this case,
we can make the arrow and radius parametric:

<pre highlight="css">

:root {
--radius: 5px;
--arrow-length: 3px;
--arrow-half-width: 2px;
--arrow-position: 70%;
--arrow-bottom-offset: calc(100% - var(--radius) - var(--arrow-length));
}

.bubble {
animation: bubble 100ms;
clip-path: shape(from var(---radius) top,
hline to calc(100% - var(---radius)),
curve to right var(---radius) with right top,
vline to var(---arrow-bottom-offset),
curve to calc(100% - var(---radius)) calc(100% - var(---arrow-length))
with right calc(100% - var(---arrow-length)),
hline to var(---arrow-position),
line by var(---arrow-half-width) var(---arrow-length),
line by var(---arrow-half-width) calc(0px - var(---arrow-length)),
hline to var(---radius),
curve to left var(---arrow-bottom-offset) with left calc(100% - var(---arrow-length)),
vline to var(---radius),
curve to var(---radius) top with left top); }
</pre>



</div>

<h5 id=interpolating-shape>
Interpolating the ''shape()'' Function</h5>

Expand Down
4 changes: 4 additions & 0 deletions css-shapes-2/images/bubble-50.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions css-shapes-2/images/bubble.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 3492c4a

Please sign in to comment.