Skip to content

Commit 3492c4a

Browse files
authored
[css-shapes-2] Add a detailed example for shape() (#11548)
* [css-shapes-2] Add detailed example for * Add SVGs * Remove animation bit
1 parent 8e1b503 commit 3492c4a

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

css-shapes-2/Overview.bs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,120 @@ The ''shape()'' Function</h4>
406406
which affects how line-joins and line-caps are rendered.
407407
</dl>
408408

409+
<h5 id=shape-examples>Using ''shape()'' to create responsive, parametric speech bubble</h5>
410+
411+
<div class=example>
412+
The ''shape()'' function enables shapes that are responsive, rather than scalable.
413+
While the ''polygon()'' shape is also responsive, it doesn't support curves.
414+
415+
To demonstrate, let's start with a speech bubble, such as the following:
416+
417+
<img src="images/bubble.svg" width=300 style="background: unset">
418+
419+
Using this shape with a ''clip-path'' can be done by using the ''path()'' function:
420+
421+
<pre highlight="css">
422+
.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") };
423+
</pre>
424+
425+
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:
426+
427+
<img src="images/bubble.svg" width=100 style="background: unset">
428+
429+
To construct this shape using the ''shape()'' function, let's start by turning all the pixel values from the ''path'' function to percentages.
430+
Note that the ''shape()'' function begins with <css>from</css>:
431+
432+
<pre highlight="css">
433+
.bubble { clip-path: shape( from 5% 0%,
434+
hline to 95%,
435+
curve to 100% 5% with 100% 0%,
436+
vline to 92%,
437+
curve to 95% 97% with 100% 97%,
438+
hline to 70%,
439+
line by -2% 3%,
440+
line by -2% -3%,
441+
hline to 5%,
442+
curve to 0% 92% with 0% 97%,
443+
vline to 5%,
444+
curve to 5% 0% with 0% 0%); }
445+
</pre>
446+
447+
To make this path responsive, as in, respond well to size changes, we will convert some of its units to ''px'' values,
448+
specifically the ones the control the curves and arrows:
449+
450+
<pre highlight="css">
451+
.bubble { clip-path: shape( from 5px 0%,
452+
hline to calc(100% - 5px),
453+
curve to 100% 5px with 100% 0%,
454+
vline to calc(100% - 8px),
455+
curve to calc(100% - 5px) calc(100% - 3px) with 100% calc(100% - 3px),
456+
hline to 70%,
457+
line by -2px 3px,
458+
line by -2px -3px,
459+
hline to 5px,
460+
curve to 0% calc(100% - 8px) with 0% calc(100% - 3px),
461+
vline to 5px,
462+
curve to 5px 0% with 0% 0%); }
463+
</pre>
464+
465+
When applied as ''clip-path'', it would looks like the following:
466+
<p>
467+
<img src="images/bubble-50.svg" width=150 style="background: unset">
468+
</p>
469+
470+
The whole speech bubble is scaled to the reference box, while the curves and arrows stay more constant.
471+
472+
Since ''shape()'' uses CSS units, we can replace some of the edges with ''position'' values:
473+
474+
<pre highlight="css">
475+
.bubble { clip-path: shape(from 5px 0,
476+
hline to calc(100% - 5px),
477+
curve to right 5px with right top,
478+
vline to calc(100% - 8px),
479+
curve to calc(100% - 5px) calc(100% - 3px) with right calc(100% - 3px),
480+
hline to 70%,
481+
line by -2px 3px,
482+
line by -2px -3px,
483+
hline to 5px,
484+
curve to left calc(100% - 8px) with left calc(100% - 3px),
485+
vline to 5px,
486+
curve to 5px top with left top); }
487+
</pre>
488+
489+
Another useful feature of ''shape()'' is that it can be used alongside CSS properties. In this case,
490+
we can make the arrow and radius parametric:
491+
492+
<pre highlight="css">
493+
494+
:root {
495+
--radius: 5px;
496+
--arrow-length: 3px;
497+
--arrow-half-width: 2px;
498+
--arrow-position: 70%;
499+
--arrow-bottom-offset: calc(100% - var(--radius) - var(--arrow-length));
500+
}
501+
502+
.bubble {
503+
animation: bubble 100ms;
504+
clip-path: shape(from var(---radius) top,
505+
hline to calc(100% - var(---radius)),
506+
curve to right var(---radius) with right top,
507+
vline to var(---arrow-bottom-offset),
508+
curve to calc(100% - var(---radius)) calc(100% - var(---arrow-length))
509+
with right calc(100% - var(---arrow-length)),
510+
hline to var(---arrow-position),
511+
line by var(---arrow-half-width) var(---arrow-length),
512+
line by var(---arrow-half-width) calc(0px - var(---arrow-length)),
513+
hline to var(---radius),
514+
curve to left var(---arrow-bottom-offset) with left calc(100% - var(---arrow-length)),
515+
vline to var(---radius),
516+
curve to var(---radius) top with left top); }
517+
</pre>
518+
519+
520+
521+
</div>
522+
409523
<h5 id=interpolating-shape>
410524
Interpolating the ''shape()'' Function</h5>
411525

css-shapes-2/images/bubble-50.svg

Lines changed: 4 additions & 0 deletions
Loading

css-shapes-2/images/bubble.svg

Lines changed: 4 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)