惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
小众软件
小众软件
Engineering at Meta
Engineering at Meta
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Check Point Blog
aimingoo的专栏
aimingoo的专栏
罗磊的独立博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
MongoDB | Blog
MongoDB | Blog
L
LINUX DO - 热门话题
酷 壳 – CoolShell
酷 壳 – CoolShell
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Help Net Security
Martin Fowler
Martin Fowler
G
GRAHAM CLULEY
Simon Willison's Weblog
Simon Willison's Weblog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
V
Vulnerabilities – Threatpost
云风的 BLOG
云风的 BLOG
博客园_首页
C
Cybersecurity and Infrastructure Security Agency CISA
量子位
Stack Overflow Blog
Stack Overflow Blog
Recent Announcements
Recent Announcements
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
I
Intezer
Scott Helme
Scott Helme
A
About on SuperTechFans
博客园 - 司徒正美
Hacker News: Ask HN
Hacker News: Ask HN
The GitHub Blog
The GitHub Blog
Forbes - Security
Forbes - Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
The Cloudflare Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Spread Privacy
Spread Privacy
T
Tailwind CSS Blog
S
Security Affairs
宝玉的分享
宝玉的分享

CSS Articles by Temani Afif

Get Ready For the Powerful CSS border-shape Property! | CSS-Tricks Let’s Play With Gap Decorations! How to Control Infinite CSS Animations (Part 2 of 2) How to Control Infinite CSS Animations (Part 1 of 2) Two Circles, One Arrow, and Anchor Positioning Making a Responsive Pyramidal Grid With Modern CSS | CSS-Tricks How to Create a CSS-only Elastic Text Effect Making Complex CSS Shapes Using shape() | CSS-Tricks Responsive Hexagon Grid Using Modern CSS | CSS-Tricks Responsive List of Avatars Using Modern CSS (Part 2) | CSS-Tricks Responsive List of Avatars Using Modern CSS (Part 1) | CSS-Tricks Perfectly Pointed Tooltips: To The Corners Perfectly Pointed Tooltips: All Four Sides Perfectly Pointed Tooltips: A Foundation Sequential linear() Animation With N Elements | CSS-Tricks Infinite Marquee Animation using Modern CSS Better CSS Shapes Using shape() — Part 4: Close and Move | CSS-Tricks Drawing CSS Shapes using corner-shape Better CSS Shapes Using shape() — Part 3: Curves | CSS-Tricks Better CSS Shapes Using shape() — Part 2: More on Arcs | CSS-Tricks Better CSS Shapes Using shape() — Part 1: Lines and Arcs | CSS-Tricks Creating Blob Shapes using clip-path: shape() Custom progress element using the attr() function A CSS-Only Star Rating Component and More! (Part 2) | CSS-Tricks A CSS-Only Star Rating Component and More! (Part 1) | CSS-Tricks How to Create Wavy Boxes Using CSS Full-Bleed Layout with Modern CSS Fancy Menu Navigation Using Anchor Positioning | CSS-Tricks How to Create a Zig-Zag Box Using CSS How to Create Zig-Zag CSS Loaders Using One Element Custom Progress Element Using Anchor Positioning & Scroll-Driven Animations How to Create Filling CSS Loaders Using One Element How to Create Curved-Edge and Rounded-Edge Shapes Using CSS CSS Tricks That Use Only One Gradient | CSS-Tricks How to create Shapes with Inner Curves using CSS Mask Custom Range Slider Using Anchor Positioning & Scroll-Driven Animations How to Get the Width/Height of Any Element in Only CSS How Keyboard Navigation Works in a CSS Game How To Create Cut-Out Shapes using The clip-path property The Modern Guide For Making CSS Shapes — Smashing Magazine css-shape.com: The Ultimate Collection of CSS-only Shapes ⚡️ Sliding 3D Image Frames In CSS — Smashing Magazine CSS Tricks To Master The clip-path Property Creating Wavy Circles with Fancy Animations in CSS Modern CSS Tooltips And Speech Bubbles (Part 2) — Smashing Magazine Do you need a Tooltip or a Speech Bubble? I have created 100 using CSS 😲 Modern CSS Tooltips And Speech Bubbles (Part 1) — Smashing Magazine Creating Flower Shapes using CSS Mask & Trigonometric Functions CSS Shapes: The Triangle The Complex But Awesome CSS border-image Property — Smashing Magazine CSS Tricks to add 3D Effects to your Text CSS Responsive Multi-Line Ribbon Shapes (Part 2) — Smashing Magazine CSS Responsive Multi-Line Ribbon Shapes (Part 1) — Smashing Magazine I have made 100+ CSS-only Ribbon Shapes | The Perfect Collection 🎀 How to create a CSS-only infinite scroll animation Re-Creating The Pop-Out Hover Effect With Modern CSS (Part 2) — Smashing Magazine Re-Creating The Pop-Out Hover Effect With Modern CSS (Part 1) — Smashing Magazine How to Create CSS Ribbon Shapes with a Single Element CSS Shapes: The Ribbon Revealing Images With CSS Mask Animations — Smashing Magazine css-loaders.com: The Biggest Collection of Loading Animations (more than 500 🤯) How To Define An Array Of Colors With CSS — Smashing Magazine CSS effects on images II Shines, Perspective, And Rotations: Fancy CSS 3D Effects For Images — Smashing Magazine What's your Lucky CSS Pattern? Check It Now! How to Add a CSS Reveal Animation to Your Images Modern Layouts using CSS Grid I created 100+ unique CSS patterns | The best collection 🤩 How to Create a Custom Range Slider Using CSS CSS Shapes: The Heart CSS Shapes: Polygon & Starburst A Text Reveal Animation using CSS CSS Tip: learn CSS the easy way! How to build a CSS-only accordion How to create Breadcrumb Navigation with CSS Different Ways to Get CSS Gradient Shadows | CSS-Tricks A CSS-only responsive Stepper component A Fancy Hover Effect For Your Avatar | CSS-Tricks How to make a zoom effect using CSS Creating a Custom Cursor using CSS CSS Infinite 3D Sliders | CSS-Tricks CSS Infinite Slider Flipping Through Polaroid Images | CSS-Tricks How to create a responsive sidebar menu using CSS CSS Infinite and Circular Rotating Image Slider | CSS-Tricks Making Static Noise From a Weird CSS Gradient Bug | CSS-Tricks CSS Grid and Custom Shapes, Part 3 | CSS-Tricks Fancy Image Decorations: Outlines and Complex Animations | CSS-Tricks Fancy Image Decorations: Masks and Advanced Hover Effects | CSS-Tricks Fancy Image Decorations: Single Element Magic | CSS-Tricks How to create an infinite image slider using CSS How to Create Wavy Shapes & Patterns in CSS | CSS-Tricks How I Made a Pure CSS Puzzle Game | CSS-Tricks How to create a Tooltip/Speech Bubble using CSS CSS Grid and Custom Shapes, Part 2 | CSS-Tricks CSS Grid and Custom Shapes, Part 1 | CSS-Tricks Zooming Images in a Grid Layout | CSS-Tricks How to create a CSS-only loader with one element Exploring CSS Grid’s Implicit Grid and Auto-Placement Powers | CSS-Tricks How to create background pattern using CSS & conic-gradient Single Element Loaders: The Bars | CSS-Tricks
Creating Flower Shapes using clip-path: shape()
Temani Afif on May 12, 2025 · 2025-05-13 · via CSS Articles by Temani Afif

In a previous article, we used modern CSS features such as mask, trigonometric functions, and CSS variables to create flower-like shapes.

The HTML code was a single element, which means we can apply the CSS to image elements and get cool frames like the demo below:

In this article, we are redoing the same shapes using the new shape() function, which I think will become my favorite CSS feature.

At the time of writing, only Chrome, Edge, and Safari have the full support of the features we will be using.

Article Series

What is shape()?

You are probably familiar with clip-path: polygon(), right? A function that allows you to specify different points, draw straight lines between them and create various CSS shapes (I invite you to check my online collection of CSS shapes to see some of them). I said “straight lines” because when it comes to curves, clip-path is very limited. We have circle() and ellipse(), but we cannot achieve complex shapes with them.

shape() is the new value that overcomes such limitation. In addition to straight lines, it allows us to draw curves. But If you check the MDN page or the specification, you can see that the syntax is a bit complex and not easy to grasp. It’s very similar to SVG path, which is good as it gives us a lot of options and flexibility, but it requires a lot of practice to get used to it.

I will not write a boring tutorial explaining the syntax and all the possible values, but rather focus on one command per article. In this article, we will study the arc command, and the next article will be about the curve command. And, of course, we are going to draw cool shapes. Otherwise it’s no fun!

The arc Command

This command allows you to draw an elliptic arc between two points but I will only consider the particular case of a circle which is easier and the one you will need the most. Let’s start with some geometry to understand how it works.

If you have two points (A and B) and a radius, there are exactly two circles with the given radius that intersect with the points. The intersection of both circles gives us 4 possible arcs between A and B that we can identify with a size (small or large) and a direction (clockwise or counter-clockwise)

The code will look like the below:

clip-path: shape(from Xa Ya, arc to Xb Yb of R [large or small] [cw or ccw])Code language: CSS (css)

The first command of a shape is always a from to give the starting point, and then we use the arc to define the ending point, the radius, the size, and the direction.

Here is a demo to illustrate the different values:

The points and the radii are the same. I am only changing the size and direction to choose one of the four possibilities. It should be noted that the size and direction aren’t mandatory. The defaults are small and ccw.

That’s all: we have what we need to draw flower shapes!

Creating The Flower Shape

I will start with a figure from the previous article.

Using the mask method, we had to draw a big circle at the center and small circles placed around it. Using shape(), we need to draw the arcs of the small circles. The starting and ending points of each arc are placed where the circles touch each other.

The code will look as follows:

.flower { 
  clip-path: shape(from X0 Y0, 
     arc to X1 Y1 of R,
     arc to X2 Y2 of R,
     arc to X3 Y3 of R,
     arc to X4 Y4 of R,
     ...
     arc to Xn Yn of R
  )
}Code language: CSS (css)

And like I did with the mask method, I will rely on Sass to create a loop.

$n: 10;

.flower {
  $m: ();
  $m: append($m,from X0 Y0,comma);
  @for $i from 1 through $n {
    $m: append($m,arc to Xi Yi of R,comma);
  } 
  clip-path: shape(#{$m});
}Code language: SCSS (scss)

Now we need to identify the radius of the small circles (R) and the position of the different points (Xi, Yi). I already did the calculation of the radius in the previous article, so I will reuse the same value:

R = 50%/(1 + 1/math.sin(180deg/$n))Code language: SCSS (scss)

For the points, they are placed around the same circle so their coordinate can be written like below:

Xi = 50% + D*math.cos($i*360deg/$n)
Yi = 50% + D*math.sin($i*360deg/$n)Code language: SCSS (scss)

Here is a figure to illustrate the distance D and the radius R:

I know you don’t want a boring geometry course so here is the value of D.

D = 50%/(math.tan(180deg/$n) + 1/math.cos(180deg/$n))Code language: SCSS (scss)

And the final code will be:

$n: 10;

.flower {
  $m: ();
  $r: 50%/(1 + 1/math.sin(180deg/$n));
  $d: 50%/(math.tan(180deg/$n) + 1/math.cos(180deg/$n));
  $m: append($m,from 
    50% + $d*math.cos(0) 
    50% + $d*math.sin(0),comma);
  @for $i from 1 through $n {
    $m: append($m,arc to 
      50% + $d*math.cos($i*360deg/$n)
      50% + $d*math.sin($i*360deg/$n)
      of $r,comma);
  } 
  clip-path: shape(#{$m});  
}Code language: SCSS (scss)

Wait, we get the inverted shape instead? Why is that?

We didn’t define the size and the direction of the arcs so by default the browser will use small and ccw. This gives us the inverted version of the flower. If you try the 4 different combinations (including the default one) you will get the following:

small ccw and large cw give us the shape we are looking for. The small cw is an interesting variation, and the large ccw is a funny one. We can consider a CSS variable to easily control which shape we want to get.

Combining Both Shapes

Now, what about the shape below?

The idea is to use the same code and alternate between two arc configurations.

$n: 10;

.flower {
  $m: ();
  $r: 50%/(1 + 1/math.sin(180deg/$n));
  $d: 50%/(math.tan(180deg/$n) + 1/math.cos(180deg/$n));
  $m: append($m,from 
    50% + $d*math.cos(0) 
    50% + $d*math.sin(0),comma);
  @for $i from 1 through $n {
    $c:small ccw;
    @if $i % 2 == 0 {$c:large cw}
    $m: append($m,arc to 
      50% + $d*math.cos($i*360deg/$n)
      50% + $d*math.sin($i*360deg/$n)
      of $r $c,comma);
  } 
  clip-path: shape(#{$m});  
}Code language: SCSS (scss)

I introduced a new variable $c within the loop that will have the value small ccw when $i is odd and large cw otherwise.

Cool right? The compiled code will look like the below:

clip-path: 
shape(from X0 Y0,
arc to X1 Y1 of R small ccw,
arc to X2 Y2 of R large cw,
arc to X3 Y3 of R small ccw,
arc to X4 Y4 of R large cw,
...
)

The first arc will use the inner curve (small ccw), the next one the outer curve (large cw) and so on. We repeat this to get our wavy-flower shape!

Optimizing The Code

We made a generic code that allow us to get any shape variation by simply controlling the size/direction of the arcs, but for each particular case, we can have a more simplified code.

For the inverted variation (small ccw), the value of D can be replaced by 50%. This will simplify the formula and also increase the area covered by the shape. We also need to update the value of the radius.

$n: 10;

.flower {
  $m: ();
  $r: 50%*math.tan(180deg/$n);
  $m: append($m,from 
    50% + 50%*math.cos(0) 
    50% + 50%*math.sin(0),comma);
  @for $i from 1 through $n {
    $m: append($m,arc to 
      50% + 50%*math.cos($i*360deg/$n)
      50% + 50%*math.sin($i*360deg/$n)
      of $r,comma);
  } 
  clip-path: shape(#{$m});  
}Code language: SCSS (scss)

We can do the same for the main shape, but this time we can simplify the value of the radius and use 1%.

$n: 10;

.flower {
  $m: ();
  $d: 50%/(math.cos(180deg/$n)*(1 + math.tan(180deg/$n)));
  $m: append($m,from 
    50% + $d*math.cos(0) 
    50% + $d*math.sin(0),comma);
  @for $i from 1 through $n {
    $m: append($m,arc to 
      50% + $d*math.cos($i*360deg/$n)
      50% + $d*math.sin($i*360deg/$n)
      of 1% cw,comma);
  } 
  clip-path: shape(#{$m});  
}Code language: CSS (css)

This one is interesting because using 1% as a radius is kind of strange and not intuitive. In the explanation of the arc command, I said that we have exactly two circles with the given radius that intersect with the two points, but what if the radius is smaller than half the distance between the points? No circles can meet that condition.

This case falls into an error handling where the browser will scale the radius until we can have at least one circle that meets the conditions (yes, it’s defined within the specification). That circle will simply have its radius equal to half the distance between both points. It also means we only have two arcs with the same size (small and large will be equal)

In other words, if you specify a small radius (like 1%), you are telling the browser to find the radius value for you (a lazy but clever move!). This trick won’t work in all the situations but can be handy in many of them so don’t forget about it.

Conclusion

We are done with this first article! You should have a good overview of the arc command and how to use it. I only studied the particular case of drawing circular arcs but once you get used to this you can move to the elliptic ones even if I think you will rarely need them.

Let’s end with a last demo of a heart shape, where I am using the arc command. Can you figure out how to do it before checking my code?

And don’t forget to bookmark my online generators from where you can get the code of the flower shapes and more!

Article Series