Home

Polygon Shapes

30 October 2021

CSS Doodle provides a declarative syntax for generating polgyon shapes with clip-path property. To create a regular polygon, simply set the number of vertices or points:

clip-path: @shape(
  points: 5;
)

You may want to rotate, scale, or move it.

clip-path: @shape(
  points: 5;
  rotate: -18;
  scale: .8;
  move: 0 .45;
)

The shape can also be made into a hollow frame.

clip-path: @shape(
  points: 5;
  frame: 5;
)

Or something like straight line paths.

clip-path: @shape(
  points: 5;
  frame: 5;
  turn: 2;
)

If there are enough points, it will look like a circle.

clip-path: @shape(
  points: 360;
)

By default the shape is defined with trigonometric functions of x and y. That is, x = cos(t) and y = sin(t), where t represents the symbol theta for the equally divided angle.

clip-path: @shape(
  points: 360;
  x: cos(t);
  y: sin(t);
)

You can change the equations to form different shapes you like.

clip-path: @shape(
  points: 360;
  scale: .32 .4;
  x: sin(t) + sin(5t) - sin(7t);
  y: cos(t) + cos(5t) - cos(3t);
)

It supports custom variables, so you can put parameters to one place.

clip-path: @shape(
  points: 200;
  scale: .12;
  k: 9;
  x: k*cos(t) + cos(k*t);
  y: k*sin(t) - sin(k*t);
)

When multiple paths are crossed it's useful to set the fill-rule to be evenodd.

clip-path: @shape(
  points: 360;
  scale: .5;
  x: cos(2t) + cos(7t);
  y: sin(2t) + sin(7t);
  fill: evenodd;
)

This shape requires evenodd to show as well.

clip-path: @shape(
  points: 360;
  scale: .5;
  x: cos(4t) + cos(5t);
  y: sin(4t) + sin(5t);
  fill: evenodd;
)

Another similar way to define the shape is to use the formula of Polar equation.

clip-path: @shape(
  points: 360;
  r: cos(4t);
)

Sometimes you may get interesting shapes with just a few vertices.

clip-path: @shape(
  points: 30;
  r: cos(4t) * sin(2t) * 1.35;
)

Even if there are only 9 vertices.

clip-path: @shape(
  points: 9;
  rotate: -40;
  move: .15 -.5;
  r: 1.5 * sin(-10.278t);
)

Let's draw a shape with Superformula.

clip-path: @shape(
  points: 360;
  m: 5;
  n: .4;
  p1: abs.cos(t*m/4)^n;
  p2: abs.sin(t*m/4)^n;
  r: 1/(p1 + p2)^(1/n);
)

It's very straightforward to draw the squircle shape in this way.

clip-path: @shape(
  points: 100;
  r: (1-.5*sin(2t)^2)^-.25;
)

The value of r doesn't have to be Math equations. It can be a constant value.

clip-path: @shape(
  points: 180;
  r: .4;
)

Use the built-in seq() function to pass in a sequence of values for each point.

clip-path: @shape(
  points: 12;
  r: seq(.6, 1);
)

In most cases, it's useful when there aren't many points.

clip-path: @shape(
  points: 36;
  frame: 10;
  r: seq(.8, 1, .618);
)

That's all the rules.

Despite its simplicity, it's worth exploring further to find more interesting shapes. For example, this vase shape that I like very much.

clip-path: @shape(
  points: 200;
  scale: .3;
  x: sin(4t) + sin(t) * 1.3;
  y: cos(t) + cos(t) * 4.9 + .3;
)

The shape will be symmetrical if the given equations are symmetrical. In this case, x has two cos's and one sin, y is the opposite.

clip-path: @shape(
  points: 360;
  fill: evenodd;
  x: cos(2t) * cos(5t) * sin(t);
  y: sin(2t) * sin(4t) * cos(5t);
)

So follow this rule it's likely to get some symmetrical shapes, like masks.

clip-path: @shape(
  points: 360;
  scale: .49;
  x: sin(5t) + sin(4t);
  -y: cos(4t) + cos(10t);
)

There are so many variants of mask shape.

clip-path: @shape(
  points: 360;
  scale: .31 .28;
  x: sin(6t) + sin(4t) + tan.sin(t);
  -y: cos(t) + cos(4t) + tan.cos(7t);
)

I can get an opera face that is symmetrical.

clip-path: @shape(
  points: 360;
  scale: .42 .5;
  x: sin(t) + sin(8t);
  -y: cos(3t) + cos(9t);
)

Or even a dog face.

clip-path: @shape(
  points: 360;
  scale: .3;
  -y: cos(7t) + cos(3t) + cos(7t);
  x: sin(8t) + sin(2t) + sin(t);
)

The fish shape is symmetrical too.

clip-path: @shape(
  points: 360;
  scale: .28;
  move: 0 .5;
  x: sin(4t) + sin(4t) + tan.sin(t);
  y: cos(5t) + cos(t) + tan.cos(8t);
)

The process of discovering new shapes is as exciting as imagining discovering new life on another planet.

clip-path: @shape(
  points: 480;
  scale: .3;
  move: 0 .35;
  x: sin(t) + sin(6t) + tan.sin(2t);
  y: cos(t) + cos(5t) + tan.cos(8t);
)

Not all shapes are symmetrical. Using parameters with large or fractional numbers you will get distinct ones.

clip-path: @shape(
  points: 180;
  scale: .08;
  x: 2 * sin(112t) + 11 * sin(t);
  y: sin(47t) + 20 * sin(5t);
)

The landscape clip is a good example of asymmetrical shapes.

clip-path: @shape(
  points: 90;
  rotate: 90;
  scale: .8;
  x: (.99 + cos(9t)) * 2.3;
  y: x^9*sin(x^8 * 3t) +
     sin(13.6x-9.01t)/cos(t);
)

This is one of my favorites :)

clip-path: @shape(
  points: 1000;
  scale: .8;
  move: .5 .64;
  x: cos(t^t) + cos(1.8^t);
  y: sin(t) + sin(2.305t)*sin(t);
)

Shapes can also be some abstract forms. Does this look like five people dancing?

clip-path: @shape(
  points: 1000;
  scale: .061 .06;
  x: (11*cos(.6t) + cos(55t) - 2.8) * -1.81;
  -y: (11*sin(9.03t) - sin(77t)) * 2.5 + 17;
)

I can't describe what exactly the shape is but it looks like somewhere by the sea.

clip-path: @shape(
  points: 360;
  scale: .42;
  move: -.5 -.78;
  x: sin(3t) + sin(2/t) + sin(4t);
  -y: cos(3t) + cos(t) + cos(2t);
)

So is this shape.

clip-path: @shape(
  points: 720;
  scale: .4 .3;
  move: -.5 0;
  -y: cos(5t) + cos(3t) + cos(5t);
  x: sin(3t) + sin(3/t) + sin(2t);
)

Creating shapes using mathematical functions is very different from other methods. It's helpful to build some kind of intuition yourself by practicing.

clip-path: @shape(
  points: 1000;
  a: 2931;
  scale: .9;
  frame: 400;
  fill: evenodd;
  x: cos(t) + cos(17t) + sin(a*t)/9;
  y: sin(t) + sin(17t) + cos(a*t)/9;
)

Several other shapes I find quite interesting and elegant. Look this plant:

clip-path: @shape(
  points: 1800;
  scale: .8;
  move: 0 1.2;
  x: sin(t) + sin(t)/2 + cos(140t)/9;
  y: cos(5t) + cos(14t)/2 + sin(121t)/9;
)

Rocks.

clip-path: @shape(
  points: 1000;
  scale: 1.5 1;
  x: cos(9t) + cos(9t)/9 + sin(139t)/2;
  y: sin(t) + sin(t)/.5 + cos(29t)/3;
)

Strings.

clip-path: @shape(
  split: 360;
  frame: 24;
  turn: .5;
  scale: .1;
  x: 9 * cos(10t) + cos(44t);
  y: 9 * sin(10t) + sin(44t);
)

Dried fish.

clip-path: @shape(
  points: 360;
  scale: .22;
  x: sin(t) + tan.sin(4t) + tan.sin(t);
  y: cos(8t) + tan.cos(3t) + tan.cos(8t);
)

Alien spaceship.

clip-path: @shape(
  points: 360;
  scale: .35;
  move: 0 1;
  x: sin(7t) + sin(6t) + tan.sin(t);
  y: cos(3t) + cos(6t) + tan.cos(3t);
)

And a person practicing Zen.

clip-path: @shape(
  points: 360;
  scale: .33;
  x: sin(3t) + sin(6t) + sin(7t);
  -y: 2*cos(t) + cos(7t);
)

Hope these examples can explain the @shape() function well. Below are the links of a live editor and all the other shapes I created for the divtober challenge this month.