Using pow() and sqrt() in CSS to make shapes with shapes

Mike Sandula - Sep 12 - - Dev Community

If you’ve been writing CSS for a while, there's a good chance you've used the calc() function before. One such use case would be when you want to make the width of an element be the width of the page minus some distance, e.g., width: calc(100vw - 16px);.

But did you know that CSS now has other math functions, such as pow() and sqrt()? These functions were introduced in December 2023 and have baseline compatibility. They work the same as JavaScript's Math.pow() and Math.sqrt() but without the Math prefix.

Let's see how we can make use of them.

Making shapes with shapes

In this CodePen, I have a circle, a triangle, and a square, each traveling a path in the shape of itself around its origin.

A circle, a triangle, and a square.

The circle and the square don’t require anything too fancy (I won't delve into it here, but you can check out the code for yourself) but the math is a bit more involved for the triangle. The animation needs to move among the three points of the triangle. In order to do this, we need the X, Y coordinates of each point, where the center is at (0, 0). These points are represented by the red dots in this image.

A triangle on a Cartesian graph where its center is at (0, 0).

The X coordinates are pretty straightforward: The top dot is at 0, and the bottom two dots are each n / 2 away from 0, where n equals the length of each side. For example, if n is 16px, then their X coordinates would be -8px and 8px, respectively.

Figuring out the Y coordinates is where things get just a bit more complicated. We'll need to first figure out the height of the triangle.

An equilateral triangle with sides of length

To do that, we'll need the Pythagorean theorem which, as you may recall from geometry class, is A² + B² = C².

The C in this case is n since that's the longest side, and A is half the length of n, or n / 2. To get B, which represents the height, we need the square root of minus (n / 2)².

I'm using a CSS variable called --size to represent n. Note that I also have a variable called --size-with-unit. I have a slider that lets you adjust the size from 1rem to 5rem, with a default value of 3rem. I'm mostly using the --size-with-unit variable throughout my CSS, but these math functions require a plain numeric value. It was easier to have two separate variables rather than worry about adding or removing units in place.

We'll use the pow() function for squaring values (This function is actually an exponential function that takes in two numbers: a base number and its exponent. When squaring a number, the second parameter will always be 2.) and the sqrt() function for calculating the square root. We'll save our calculation to a --height variable, which looks like this:

.triangle {
  --height: calc(
    1rem * (sqrt(pow(var(--size), 2) - pow(calc(var(--size) / 2), 2)))
  );
}
Enter fullscreen mode Exit fullscreen mode

Since we're traveling relative to our center origin, we'll go either half the distance of our height upwards or downwards. We'll save this to a variable called --midpoint, which is equal to calc(var(--height) / 2).

Now we have our X, Y coordinates:

  • (-(size / 2), -midpoint)
  • (0, midpoint)
  • (size / 2, -midpoint)

Put it all together, and now our triangle can, well, triangulate (while the circle circulates and the square ... does its thing)!

A GIF of a circle going in a circle, a triangle going in a triangle, and a square going in a square.

Conclusion

This was a contrived example, of course, but hopefully you can see the pow-er of these new CSS functions 😆. Good luck and happy coding!

Note: In case you're curious, I used Excalidraw to create the images in this post.

. .
Terabox Video Player